2018-08-11 13:19:58 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2013-03-24 07:11:31 +08:00
|
|
|
/*
|
|
|
|
* bcache setup/teardown code, and some metadata io - read a superblock and
|
|
|
|
* figure out what to do with it.
|
|
|
|
*
|
|
|
|
* Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
|
|
|
|
* Copyright 2012 Google, Inc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "bcache.h"
|
|
|
|
#include "btree.h"
|
|
|
|
#include "debug.h"
|
2013-12-21 09:22:05 +08:00
|
|
|
#include "extents.h"
|
2013-03-24 07:11:31 +08:00
|
|
|
#include "request.h"
|
2013-06-05 21:21:07 +08:00
|
|
|
#include "writeback.h"
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-27 06:39:55 +08:00
|
|
|
#include <linux/blkdev.h>
|
2013-03-24 07:11:31 +08:00
|
|
|
#include <linux/buffer_head.h>
|
|
|
|
#include <linux/debugfs.h>
|
|
|
|
#include <linux/genhd.h>
|
2013-07-31 16:12:02 +08:00
|
|
|
#include <linux/idr.h>
|
2013-07-11 09:31:58 +08:00
|
|
|
#include <linux/kthread.h>
|
2013-03-24 07:11:31 +08:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/random.h>
|
|
|
|
#include <linux/reboot.h>
|
|
|
|
#include <linux/sysfs.h>
|
|
|
|
|
2018-12-13 22:53:55 +08:00
|
|
|
unsigned int bch_cutoff_writeback;
|
|
|
|
unsigned int bch_cutoff_writeback_sync;
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
static const char bcache_magic[] = {
|
|
|
|
0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
|
|
|
|
0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char invalid_uuid[] = {
|
|
|
|
0xa0, 0x3e, 0xf8, 0xed, 0x3e, 0xe1, 0xb8, 0x78,
|
|
|
|
0xc8, 0x50, 0xfc, 0x5e, 0xcb, 0x16, 0xcd, 0x99
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct kobject *bcache_kobj;
|
|
|
|
struct mutex bch_register_lock;
|
|
|
|
LIST_HEAD(bch_cache_sets);
|
|
|
|
static LIST_HEAD(uncached_devices);
|
|
|
|
|
2013-07-31 16:12:02 +08:00
|
|
|
static int bcache_major;
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
static DEFINE_IDA(bcache_device_idx);
|
2013-03-24 07:11:31 +08:00
|
|
|
static wait_queue_head_t unregister_wait;
|
|
|
|
struct workqueue_struct *bcache_wq;
|
2018-09-27 23:41:46 +08:00
|
|
|
struct workqueue_struct *bch_journal_wq;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
#define BTREE_MAX_PAGES (256 * 1024 / PAGE_SIZE)
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
/* limitation of partitions number on single bcache device */
|
|
|
|
#define BCACHE_MINORS 128
|
|
|
|
/* limitation of bcache devices number on single system */
|
|
|
|
#define BCACHE_DEVICE_IDX_MAX ((1U << MINORBITS)/BCACHE_MINORS)
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
/* Superblock */
|
|
|
|
|
|
|
|
static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
|
|
|
|
struct page **res)
|
|
|
|
{
|
|
|
|
const char *err;
|
|
|
|
struct cache_sb *s;
|
|
|
|
struct buffer_head *bh = __bread(bdev, 1, SB_SIZE);
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
if (!bh)
|
|
|
|
return "IO error";
|
|
|
|
|
|
|
|
s = (struct cache_sb *) bh->b_data;
|
|
|
|
|
|
|
|
sb->offset = le64_to_cpu(s->offset);
|
|
|
|
sb->version = le64_to_cpu(s->version);
|
|
|
|
|
|
|
|
memcpy(sb->magic, s->magic, 16);
|
|
|
|
memcpy(sb->uuid, s->uuid, 16);
|
|
|
|
memcpy(sb->set_uuid, s->set_uuid, 16);
|
|
|
|
memcpy(sb->label, s->label, SB_LABEL_SIZE);
|
|
|
|
|
|
|
|
sb->flags = le64_to_cpu(s->flags);
|
|
|
|
sb->seq = le64_to_cpu(s->seq);
|
|
|
|
sb->last_mount = le32_to_cpu(s->last_mount);
|
|
|
|
sb->first_bucket = le16_to_cpu(s->first_bucket);
|
|
|
|
sb->keys = le16_to_cpu(s->keys);
|
|
|
|
|
|
|
|
for (i = 0; i < SB_JOURNAL_BUCKETS; i++)
|
|
|
|
sb->d[i] = le64_to_cpu(s->d[i]);
|
|
|
|
|
|
|
|
pr_debug("read sb version %llu, flags %llu, seq %llu, journal size %u",
|
|
|
|
sb->version, sb->flags, sb->seq, sb->keys);
|
|
|
|
|
|
|
|
err = "Not a bcache superblock";
|
|
|
|
if (sb->offset != SB_SECTOR)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (memcmp(sb->magic, bcache_magic, 16))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
err = "Too many journal buckets";
|
|
|
|
if (sb->keys > SB_JOURNAL_BUCKETS)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
err = "Bad checksum";
|
|
|
|
if (s->csum != csum_set(s))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
err = "Bad UUID";
|
2013-03-29 02:50:55 +08:00
|
|
|
if (bch_is_zero(sb->uuid, 16))
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
2013-04-24 12:51:48 +08:00
|
|
|
sb->block_size = le16_to_cpu(s->block_size);
|
|
|
|
|
|
|
|
err = "Superblock block size smaller than device block size";
|
|
|
|
if (sb->block_size << 9 < bdev_logical_block_size(bdev))
|
|
|
|
goto err;
|
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
switch (sb->version) {
|
|
|
|
case BCACHE_SB_VERSION_BDEV:
|
|
|
|
sb->data_offset = BDEV_DATA_START_DEFAULT;
|
|
|
|
break;
|
|
|
|
case BCACHE_SB_VERSION_BDEV_WITH_OFFSET:
|
|
|
|
sb->data_offset = le64_to_cpu(s->data_offset);
|
|
|
|
|
|
|
|
err = "Bad data offset";
|
|
|
|
if (sb->data_offset < BDEV_DATA_START_DEFAULT)
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
break;
|
|
|
|
case BCACHE_SB_VERSION_CDEV:
|
|
|
|
case BCACHE_SB_VERSION_CDEV_WITH_UUID:
|
|
|
|
sb->nbuckets = le64_to_cpu(s->nbuckets);
|
|
|
|
sb->bucket_size = le16_to_cpu(s->bucket_size);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
sb->nr_in_set = le16_to_cpu(s->nr_in_set);
|
|
|
|
sb->nr_this_dev = le16_to_cpu(s->nr_this_dev);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Too many buckets";
|
|
|
|
if (sb->nbuckets > LONG_MAX)
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Not enough buckets";
|
|
|
|
if (sb->nbuckets < 1 << 7)
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Bad block/bucket size";
|
|
|
|
if (!is_power_of_2(sb->block_size) ||
|
|
|
|
sb->block_size > PAGE_SECTORS ||
|
|
|
|
!is_power_of_2(sb->bucket_size) ||
|
|
|
|
sb->bucket_size < PAGE_SECTORS)
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Invalid superblock: device too small";
|
2018-08-11 13:19:47 +08:00
|
|
|
if (get_capacity(bdev->bd_disk) <
|
|
|
|
sb->bucket_size * sb->nbuckets)
|
2013-04-12 06:14:35 +08:00
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Bad UUID";
|
|
|
|
if (bch_is_zero(sb->set_uuid, 16))
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Bad cache device number in set";
|
|
|
|
if (!sb->nr_in_set ||
|
|
|
|
sb->nr_in_set <= sb->nr_this_dev ||
|
|
|
|
sb->nr_in_set > MAX_CACHES_PER_SET)
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Journal buckets not sequential";
|
|
|
|
for (i = 0; i < sb->keys; i++)
|
|
|
|
if (sb->d[i] != sb->first_bucket + i)
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
err = "Too many journal buckets";
|
|
|
|
if (sb->first_bucket + sb->keys > sb->nbuckets)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
err = "Invalid superblock: first bucket comes before end of super";
|
|
|
|
if (sb->first_bucket * sb->bucket_size < 16)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = "Unsupported superblock version";
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
2013-04-12 06:14:35 +08:00
|
|
|
}
|
|
|
|
|
2018-07-26 12:17:41 +08:00
|
|
|
sb->last_mount = (u32)ktime_get_real_seconds();
|
2013-03-24 07:11:31 +08:00
|
|
|
err = NULL;
|
|
|
|
|
|
|
|
get_page(bh->b_page);
|
|
|
|
*res = bh->b_page;
|
|
|
|
err:
|
|
|
|
put_bh(bh);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2015-07-20 21:29:37 +08:00
|
|
|
static void write_bdev_super_endio(struct bio *bio)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
struct cached_dev *dc = bio->bi_private;
|
2019-06-28 19:59:30 +08:00
|
|
|
|
|
|
|
if (bio->bi_status)
|
|
|
|
bch_count_backing_io_errors(dc, bio);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
closure_put(&dc->sb_write);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __write_super(struct cache_sb *sb, struct bio *bio)
|
|
|
|
{
|
2017-12-18 20:22:04 +08:00
|
|
|
struct cache_sb *out = page_address(bio_first_page_all(bio));
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-10-12 06:44:27 +08:00
|
|
|
bio->bi_iter.bi_sector = SB_SECTOR;
|
|
|
|
bio->bi_iter.bi_size = SB_SIZE;
|
2016-06-06 03:32:05 +08:00
|
|
|
bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC|REQ_META);
|
2013-03-29 02:50:55 +08:00
|
|
|
bch_bio_map(bio, NULL);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
out->offset = cpu_to_le64(sb->offset);
|
|
|
|
out->version = cpu_to_le64(sb->version);
|
|
|
|
|
|
|
|
memcpy(out->uuid, sb->uuid, 16);
|
|
|
|
memcpy(out->set_uuid, sb->set_uuid, 16);
|
|
|
|
memcpy(out->label, sb->label, SB_LABEL_SIZE);
|
|
|
|
|
|
|
|
out->flags = cpu_to_le64(sb->flags);
|
|
|
|
out->seq = cpu_to_le64(sb->seq);
|
|
|
|
|
|
|
|
out->last_mount = cpu_to_le32(sb->last_mount);
|
|
|
|
out->first_bucket = cpu_to_le16(sb->first_bucket);
|
|
|
|
out->keys = cpu_to_le16(sb->keys);
|
|
|
|
|
|
|
|
for (i = 0; i < sb->keys; i++)
|
|
|
|
out->d[i] = cpu_to_le64(sb->d[i]);
|
|
|
|
|
|
|
|
out->csum = csum_set(out);
|
|
|
|
|
|
|
|
pr_debug("ver %llu, flags %llu, seq %llu",
|
|
|
|
sb->version, sb->flags, sb->seq);
|
|
|
|
|
2016-06-06 03:31:41 +08:00
|
|
|
submit_bio(bio);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
static void bch_write_bdev_super_unlock(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cached_dev *dc = container_of(cl, struct cached_dev, sb_write);
|
|
|
|
|
|
|
|
up(&dc->sb_write_mutex);
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent)
|
|
|
|
{
|
2013-12-17 07:27:25 +08:00
|
|
|
struct closure *cl = &dc->sb_write;
|
2013-03-24 07:11:31 +08:00
|
|
|
struct bio *bio = &dc->sb_bio;
|
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
down(&dc->sb_write_mutex);
|
|
|
|
closure_init(cl, parent);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
bio_reset(bio);
|
2017-08-24 01:10:32 +08:00
|
|
|
bio_set_dev(bio, dc->bdev);
|
2013-03-24 07:11:31 +08:00
|
|
|
bio->bi_end_io = write_bdev_super_endio;
|
|
|
|
bio->bi_private = dc;
|
|
|
|
|
|
|
|
closure_get(cl);
|
2018-03-19 08:36:24 +08:00
|
|
|
/* I/O request sent to backing device */
|
2013-03-24 07:11:31 +08:00
|
|
|
__write_super(&dc->sb, bio);
|
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
closure_return_with_destructor(cl, bch_write_bdev_super_unlock);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
2015-07-20 21:29:37 +08:00
|
|
|
static void write_super_endio(struct bio *bio)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
struct cache *ca = bio->bi_private;
|
|
|
|
|
2018-01-09 04:21:29 +08:00
|
|
|
/* is_read = 0 */
|
|
|
|
bch_count_io_errors(ca, bio->bi_status, 0,
|
|
|
|
"writing superblock");
|
2013-12-17 07:27:25 +08:00
|
|
|
closure_put(&ca->set->sb_write);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bcache_write_super_unlock(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cache_set *c = container_of(cl, struct cache_set, sb_write);
|
|
|
|
|
|
|
|
up(&c->sb_write_mutex);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void bcache_write_super(struct cache_set *c)
|
|
|
|
{
|
2013-12-17 07:27:25 +08:00
|
|
|
struct closure *cl = &c->sb_write;
|
2013-03-24 07:11:31 +08:00
|
|
|
struct cache *ca;
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
down(&c->sb_write_mutex);
|
|
|
|
closure_init(cl, &c->cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
c->sb.seq++;
|
|
|
|
|
|
|
|
for_each_cache(ca, c, i) {
|
|
|
|
struct bio *bio = &ca->sb_bio;
|
|
|
|
|
2013-04-12 06:14:35 +08:00
|
|
|
ca->sb.version = BCACHE_SB_VERSION_CDEV_WITH_UUID;
|
2013-03-24 07:11:31 +08:00
|
|
|
ca->sb.seq = c->sb.seq;
|
|
|
|
ca->sb.last_mount = c->sb.last_mount;
|
|
|
|
|
|
|
|
SET_CACHE_SYNC(&ca->sb, CACHE_SYNC(&c->sb));
|
|
|
|
|
|
|
|
bio_reset(bio);
|
2017-08-24 01:10:32 +08:00
|
|
|
bio_set_dev(bio, ca->bdev);
|
2013-03-24 07:11:31 +08:00
|
|
|
bio->bi_end_io = write_super_endio;
|
|
|
|
bio->bi_private = ca;
|
|
|
|
|
|
|
|
closure_get(cl);
|
|
|
|
__write_super(&ca->sb, bio);
|
|
|
|
}
|
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
closure_return_with_destructor(cl, bcache_write_super_unlock);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* UUID io */
|
|
|
|
|
2015-07-20 21:29:37 +08:00
|
|
|
static void uuid_endio(struct bio *bio)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
struct closure *cl = bio->bi_private;
|
2013-12-17 07:27:25 +08:00
|
|
|
struct cache_set *c = container_of(cl, struct cache_set, uuid_write);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2017-06-03 15:38:06 +08:00
|
|
|
cache_set_err_on(bio->bi_status, c, "accessing uuids");
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_bbio_free(bio, c);
|
|
|
|
closure_put(cl);
|
|
|
|
}
|
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
static void uuid_io_unlock(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cache_set *c = container_of(cl, struct cache_set, uuid_write);
|
|
|
|
|
|
|
|
up(&c->uuid_write_mutex);
|
|
|
|
}
|
|
|
|
|
2016-06-06 03:32:05 +08:00
|
|
|
static void uuid_io(struct cache_set *c, int op, unsigned long op_flags,
|
2013-03-24 07:11:31 +08:00
|
|
|
struct bkey *k, struct closure *parent)
|
|
|
|
{
|
2013-12-17 07:27:25 +08:00
|
|
|
struct closure *cl = &c->uuid_write;
|
2013-03-24 07:11:31 +08:00
|
|
|
struct uuid_entry *u;
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-05-15 11:33:16 +08:00
|
|
|
char buf[80];
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
BUG_ON(!parent);
|
2013-12-17 07:27:25 +08:00
|
|
|
down(&c->uuid_write_mutex);
|
|
|
|
closure_init(cl, parent);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
for (i = 0; i < KEY_PTRS(k); i++) {
|
|
|
|
struct bio *bio = bch_bbio_alloc(c);
|
|
|
|
|
2016-08-06 05:35:16 +08:00
|
|
|
bio->bi_opf = REQ_SYNC | REQ_META | op_flags;
|
2013-10-12 06:44:27 +08:00
|
|
|
bio->bi_iter.bi_size = KEY_SIZE(k) << 9;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
bio->bi_end_io = uuid_endio;
|
|
|
|
bio->bi_private = cl;
|
2016-06-06 03:32:05 +08:00
|
|
|
bio_set_op_attrs(bio, op, REQ_SYNC|REQ_META|op_flags);
|
2013-03-29 02:50:55 +08:00
|
|
|
bch_bio_map(bio, c->uuids);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
bch_submit_bbio(bio, c, k, i);
|
|
|
|
|
2016-06-06 03:32:05 +08:00
|
|
|
if (op != REQ_OP_WRITE)
|
2013-03-24 07:11:31 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-12-18 15:47:33 +08:00
|
|
|
bch_extent_to_text(buf, sizeof(buf), k);
|
2016-06-06 03:32:05 +08:00
|
|
|
pr_debug("%s UUIDs at %s", op == REQ_OP_WRITE ? "wrote" : "read", buf);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
for (u = c->uuids; u < c->uuids + c->nr_uuids; u++)
|
2013-03-29 02:50:55 +08:00
|
|
|
if (!bch_is_zero(u->uuid, 16))
|
2013-03-24 07:11:31 +08:00
|
|
|
pr_debug("Slot %zi: %pU: %s: 1st: %u last: %u inv: %u",
|
|
|
|
u - c->uuids, u->uuid, u->label,
|
|
|
|
u->first_reg, u->last_reg, u->invalidated);
|
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
closure_return_with_destructor(cl, uuid_io_unlock);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *uuid_read(struct cache_set *c, struct jset *j, struct closure *cl)
|
|
|
|
{
|
|
|
|
struct bkey *k = &j->uuid_bucket;
|
|
|
|
|
2013-12-21 09:22:05 +08:00
|
|
|
if (__bch_btree_ptr_invalid(c, k))
|
2013-03-24 07:11:31 +08:00
|
|
|
return "bad uuid pointer";
|
|
|
|
|
|
|
|
bkey_copy(&c->uuid_bucket, k);
|
2016-11-01 21:40:10 +08:00
|
|
|
uuid_io(c, REQ_OP_READ, 0, k, cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
if (j->version < BCACHE_JSET_VERSION_UUIDv1) {
|
|
|
|
struct uuid_entry_v0 *u0 = (void *) c->uuids;
|
|
|
|
struct uuid_entry *u1 = (void *) c->uuids;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
closure_sync(cl);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since the new uuid entry is bigger than the old, we have to
|
|
|
|
* convert starting at the highest memory address and work down
|
|
|
|
* in order to do it in place
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i = c->nr_uuids - 1;
|
|
|
|
i >= 0;
|
|
|
|
--i) {
|
|
|
|
memcpy(u1[i].uuid, u0[i].uuid, 16);
|
|
|
|
memcpy(u1[i].label, u0[i].label, 32);
|
|
|
|
|
|
|
|
u1[i].first_reg = u0[i].first_reg;
|
|
|
|
u1[i].last_reg = u0[i].last_reg;
|
|
|
|
u1[i].invalidated = u0[i].invalidated;
|
|
|
|
|
|
|
|
u1[i].flags = 0;
|
|
|
|
u1[i].sectors = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __uuid_write(struct cache_set *c)
|
|
|
|
{
|
|
|
|
BKEY_PADDED(key) k;
|
|
|
|
struct closure cl;
|
2018-10-08 20:41:07 +08:00
|
|
|
struct cache *ca;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-08-11 13:19:45 +08:00
|
|
|
closure_init_stack(&cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
lockdep_assert_held(&bch_register_lock);
|
|
|
|
|
2013-12-17 17:29:34 +08:00
|
|
|
if (bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, true))
|
2013-03-24 07:11:31 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
SET_KEY_SIZE(&k.key, c->sb.bucket_size);
|
2016-06-06 03:32:05 +08:00
|
|
|
uuid_io(c, REQ_OP_WRITE, 0, &k.key, &cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_sync(&cl);
|
|
|
|
|
2018-10-08 20:41:07 +08:00
|
|
|
/* Only one bucket used for uuid write */
|
|
|
|
ca = PTR_CACHE(c, &k.key, 0);
|
|
|
|
atomic_long_add(ca->sb.bucket_size, &ca->meta_sectors_written);
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
bkey_copy(&c->uuid_bucket, &k.key);
|
2013-07-25 07:46:42 +08:00
|
|
|
bkey_put(c, &k.key);
|
2013-03-24 07:11:31 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bch_uuid_write(struct cache_set *c)
|
|
|
|
{
|
|
|
|
int ret = __uuid_write(c);
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
bch_journal_meta(c, NULL);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct uuid_entry *uuid_find(struct cache_set *c, const char *uuid)
|
|
|
|
{
|
|
|
|
struct uuid_entry *u;
|
|
|
|
|
|
|
|
for (u = c->uuids;
|
|
|
|
u < c->uuids + c->nr_uuids; u++)
|
|
|
|
if (!memcmp(u->uuid, uuid, 16))
|
|
|
|
return u;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct uuid_entry *uuid_find_empty(struct cache_set *c)
|
|
|
|
{
|
|
|
|
static const char zero_uuid[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
return uuid_find(c, zero_uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bucket priorities/gens:
|
|
|
|
*
|
|
|
|
* For each bucket, we store on disk its
|
2018-08-11 13:19:55 +08:00
|
|
|
* 8 bit gen
|
|
|
|
* 16 bit priority
|
2013-03-24 07:11:31 +08:00
|
|
|
*
|
|
|
|
* See alloc.c for an explanation of the gen. The priority is used to implement
|
|
|
|
* lru (and in the future other) cache replacement policies; for most purposes
|
|
|
|
* it's just an opaque integer.
|
|
|
|
*
|
|
|
|
* The gens and the priorities don't have a whole lot to do with each other, and
|
|
|
|
* it's actually the gens that must be written out at specific times - it's no
|
|
|
|
* big deal if the priorities don't get written, if we lose them we just reuse
|
|
|
|
* buckets in suboptimal order.
|
|
|
|
*
|
|
|
|
* On disk they're stored in a packed array, and in as many buckets are required
|
|
|
|
* to fit them all. The buckets we use to store them form a list; the journal
|
|
|
|
* header points to the first bucket, the first bucket points to the second
|
|
|
|
* bucket, et cetera.
|
|
|
|
*
|
|
|
|
* This code is used by the allocation code; periodically (whenever it runs out
|
|
|
|
* of buckets to allocate from) the allocation code will invalidate some
|
|
|
|
* buckets, but it can't use those buckets until their new gens are safely on
|
|
|
|
* disk.
|
|
|
|
*/
|
|
|
|
|
2015-07-20 21:29:37 +08:00
|
|
|
static void prio_endio(struct bio *bio)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
struct cache *ca = bio->bi_private;
|
|
|
|
|
2017-06-03 15:38:06 +08:00
|
|
|
cache_set_err_on(bio->bi_status, ca->set, "accessing priorities");
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_bbio_free(bio, ca->set);
|
|
|
|
closure_put(&ca->prio);
|
|
|
|
}
|
|
|
|
|
2016-06-06 03:32:05 +08:00
|
|
|
static void prio_io(struct cache *ca, uint64_t bucket, int op,
|
|
|
|
unsigned long op_flags)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
struct closure *cl = &ca->prio;
|
|
|
|
struct bio *bio = bch_bbio_alloc(ca->set);
|
|
|
|
|
|
|
|
closure_init_stack(cl);
|
|
|
|
|
2013-10-12 06:44:27 +08:00
|
|
|
bio->bi_iter.bi_sector = bucket * ca->sb.bucket_size;
|
2017-08-24 01:10:32 +08:00
|
|
|
bio_set_dev(bio, ca->bdev);
|
2013-10-12 06:44:27 +08:00
|
|
|
bio->bi_iter.bi_size = bucket_bytes(ca);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
bio->bi_end_io = prio_endio;
|
|
|
|
bio->bi_private = ca;
|
2016-06-06 03:32:05 +08:00
|
|
|
bio_set_op_attrs(bio, op, REQ_SYNC|REQ_META|op_flags);
|
2013-03-29 02:50:55 +08:00
|
|
|
bch_bio_map(bio, ca->disk_buckets);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
bcache: add CACHE_SET_IO_DISABLE to struct cache_set flags
When too many I/Os failed on cache device, bch_cache_set_error() is called
in the error handling code path to retire whole problematic cache set. If
new I/O requests continue to come and take refcount dc->count, the cache
set won't be retired immediately, this is a problem.
Further more, there are several kernel thread and self-armed kernel work
may still running after bch_cache_set_error() is called. It needs to wait
quite a while for them to stop, or they won't stop at all. They also
prevent the cache set from being retired.
The solution in this patch is, to add per cache set flag to disable I/O
request on this cache and all attached backing devices. Then new coming I/O
requests can be rejected in *_make_request() before taking refcount, kernel
threads and self-armed kernel worker can stop very fast when flags bit
CACHE_SET_IO_DISABLE is set.
Because bcache also do internal I/Os for writeback, garbage collection,
bucket allocation, journaling, this kind of I/O should be disabled after
bch_cache_set_error() is called. So closure_bio_submit() is modified to
check whether CACHE_SET_IO_DISABLE is set on cache_set->flags. If set,
closure_bio_submit() will set bio->bi_status to BLK_STS_IOERR and
return, generic_make_request() won't be called.
A sysfs interface is also added to set or clear CACHE_SET_IO_DISABLE bit
from cache_set->flags, to disable or enable cache set I/O for debugging. It
is helpful to trigger more corner case issues for failed cache device.
Changelog
v4, add wait_for_kthread_stop(), and call it before exits writeback and gc
kernel threads.
v3, change CACHE_SET_IO_DISABLE from 4 to 3, since it is bit index.
remove "bcache: " prefix when printing out kernel message.
v2, more changes by previous review,
- Use CACHE_SET_IO_DISABLE of cache_set->flags, suggested by Junhui.
- Check CACHE_SET_IO_DISABLE in bch_btree_gc() to stop a while-loop, this
is reported and inspired from origal patch of Pavel Vazharov.
v1, initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Pavel Vazharov <freakpv@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:17 +08:00
|
|
|
closure_bio_submit(ca->set, bio, &ca->prio);
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_sync(cl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void bch_prio_write(struct cache *ca)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct bucket *b;
|
|
|
|
struct closure cl;
|
|
|
|
|
|
|
|
closure_init_stack(&cl);
|
|
|
|
|
|
|
|
lockdep_assert_held(&ca->set->bucket_lock);
|
|
|
|
|
|
|
|
ca->disk_buckets->seq++;
|
|
|
|
|
|
|
|
atomic_long_add(ca->sb.bucket_size * prio_buckets(ca),
|
|
|
|
&ca->meta_sectors_written);
|
|
|
|
|
2013-12-17 17:29:34 +08:00
|
|
|
//pr_debug("free %zu, free_inc %zu, unused %zu", fifo_used(&ca->free),
|
|
|
|
// fifo_used(&ca->free_inc), fifo_used(&ca->unused));
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
for (i = prio_buckets(ca) - 1; i >= 0; --i) {
|
|
|
|
long bucket;
|
|
|
|
struct prio_set *p = ca->disk_buckets;
|
2013-03-26 02:46:44 +08:00
|
|
|
struct bucket_disk *d = p->data;
|
|
|
|
struct bucket_disk *end = d + prios_per_bucket(ca);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
for (b = ca->buckets + i * prios_per_bucket(ca);
|
|
|
|
b < ca->buckets + ca->sb.nbuckets && d < end;
|
|
|
|
b++, d++) {
|
|
|
|
d->prio = cpu_to_le16(b->prio);
|
|
|
|
d->gen = b->gen;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->next_bucket = ca->prio_buckets[i + 1];
|
2013-11-01 06:46:42 +08:00
|
|
|
p->magic = pset_magic(&ca->sb);
|
2013-03-29 02:50:55 +08:00
|
|
|
p->csum = bch_crc64(&p->magic, bucket_bytes(ca) - 8);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-12-17 17:29:34 +08:00
|
|
|
bucket = bch_bucket_alloc(ca, RESERVE_PRIO, true);
|
2013-03-24 07:11:31 +08:00
|
|
|
BUG_ON(bucket == -1);
|
|
|
|
|
|
|
|
mutex_unlock(&ca->set->bucket_lock);
|
2016-06-06 03:32:05 +08:00
|
|
|
prio_io(ca, bucket, REQ_OP_WRITE, 0);
|
2013-03-24 07:11:31 +08:00
|
|
|
mutex_lock(&ca->set->bucket_lock);
|
|
|
|
|
|
|
|
ca->prio_buckets[i] = bucket;
|
|
|
|
atomic_dec_bug(&ca->buckets[bucket].pin);
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_unlock(&ca->set->bucket_lock);
|
|
|
|
|
|
|
|
bch_journal_meta(ca->set, &cl);
|
|
|
|
closure_sync(&cl);
|
|
|
|
|
|
|
|
mutex_lock(&ca->set->bucket_lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't want the old priorities to get garbage collected until after we
|
|
|
|
* finish writing the new ones, and they're journalled
|
|
|
|
*/
|
2014-03-18 07:55:55 +08:00
|
|
|
for (i = 0; i < prio_buckets(ca); i++) {
|
|
|
|
if (ca->prio_last_buckets[i])
|
|
|
|
__bch_bucket_free(ca,
|
|
|
|
&ca->buckets[ca->prio_last_buckets[i]]);
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
ca->prio_last_buckets[i] = ca->prio_buckets[i];
|
2014-03-18 07:55:55 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void prio_read(struct cache *ca, uint64_t bucket)
|
|
|
|
{
|
|
|
|
struct prio_set *p = ca->disk_buckets;
|
|
|
|
struct bucket_disk *d = p->data + prios_per_bucket(ca), *end = d;
|
|
|
|
struct bucket *b;
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int bucket_nr = 0;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
for (b = ca->buckets;
|
|
|
|
b < ca->buckets + ca->sb.nbuckets;
|
|
|
|
b++, d++) {
|
|
|
|
if (d == end) {
|
|
|
|
ca->prio_buckets[bucket_nr] = bucket;
|
|
|
|
ca->prio_last_buckets[bucket_nr] = bucket;
|
|
|
|
bucket_nr++;
|
|
|
|
|
2016-11-01 21:40:10 +08:00
|
|
|
prio_io(ca, bucket, REQ_OP_READ, 0);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-08-11 13:19:47 +08:00
|
|
|
if (p->csum !=
|
|
|
|
bch_crc64(&p->magic, bucket_bytes(ca) - 8))
|
2013-03-24 07:11:31 +08:00
|
|
|
pr_warn("bad csum reading priorities");
|
|
|
|
|
2013-11-01 06:46:42 +08:00
|
|
|
if (p->magic != pset_magic(&ca->sb))
|
2013-03-24 07:11:31 +08:00
|
|
|
pr_warn("bad magic reading priorities");
|
|
|
|
|
|
|
|
bucket = p->next_bucket;
|
|
|
|
d = p->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
b->prio = le16_to_cpu(d->prio);
|
2014-02-28 09:51:12 +08:00
|
|
|
b->gen = b->last_gc = d->gen;
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Bcache device */
|
|
|
|
|
|
|
|
static int open_dev(struct block_device *b, fmode_t mode)
|
|
|
|
{
|
|
|
|
struct bcache_device *d = b->bd_disk->private_data;
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
if (test_bit(BCACHE_DEV_CLOSING, &d->flags))
|
2013-03-24 07:11:31 +08:00
|
|
|
return -ENXIO;
|
|
|
|
|
|
|
|
closure_get(&d->cl);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-10 04:39:26 +08:00
|
|
|
static void release_dev(struct gendisk *b, fmode_t mode)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
struct bcache_device *d = b->private_data;
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_put(&d->cl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ioctl_dev(struct block_device *b, fmode_t mode,
|
|
|
|
unsigned int cmd, unsigned long arg)
|
|
|
|
{
|
|
|
|
struct bcache_device *d = b->bd_disk->private_data;
|
bcache: stop bcache device when backing device is offline
Currently bcache does not handle backing device failure, if backing
device is offline and disconnected from system, its bcache device can still
be accessible. If the bcache device is in writeback mode, I/O requests even
can success if the requests hit on cache device. That is to say, when and
how bcache handles offline backing device is undefined.
This patch tries to handle backing device offline in a rather simple way,
- Add cached_dev->status_update_thread kernel thread to update backing
device status in every 1 second.
- Add cached_dev->offline_seconds to record how many seconds the backing
device is observed to be offline. If the backing device is offline for
BACKING_DEV_OFFLINE_TIMEOUT (30) seconds, set dc->io_disable to 1 and
call bcache_device_stop() to stop the bache device which linked to the
offline backing device.
Now if a backing device is offline for BACKING_DEV_OFFLINE_TIMEOUT seconds,
its bcache device will be removed, then user space application writing on
it will get error immediately, and handler the device failure in time.
This patch is quite simple, does not handle more complicated situations.
Once the bcache device is stopped, users need to recovery the backing
device, register and attach it manually.
Changelog:
v3: call wait_for_kthread_stop() before exits kernel thread.
v2: remove "bcache: " prefix when calling pr_warn().
v1: initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-05-28 15:37:41 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
return d->ioctl(d, mode, cmd, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct block_device_operations bcache_ops = {
|
|
|
|
.open = open_dev,
|
|
|
|
.release = release_dev,
|
|
|
|
.ioctl = ioctl_dev,
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
};
|
|
|
|
|
|
|
|
void bcache_device_stop(struct bcache_device *d)
|
|
|
|
{
|
2013-08-22 08:49:09 +08:00
|
|
|
if (!test_and_set_bit(BCACHE_DEV_CLOSING, &d->flags))
|
2019-04-25 00:48:39 +08:00
|
|
|
/*
|
|
|
|
* closure_fn set to
|
|
|
|
* - cached device: cached_dev_flush()
|
|
|
|
* - flash dev: flash_dev_flush()
|
|
|
|
*/
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_queue(&d->cl);
|
|
|
|
}
|
|
|
|
|
2013-02-01 23:29:41 +08:00
|
|
|
static void bcache_device_unlink(struct bcache_device *d)
|
|
|
|
{
|
2013-08-22 08:49:09 +08:00
|
|
|
lockdep_assert_held(&bch_register_lock);
|
2013-02-01 23:29:41 +08:00
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
if (d->c && !test_and_set_bit(BCACHE_DEV_UNLINK_DONE, &d->flags)) {
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-08-22 08:49:09 +08:00
|
|
|
struct cache *ca;
|
2013-02-01 23:29:41 +08:00
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
sysfs_remove_link(&d->c->kobj, d->name);
|
|
|
|
sysfs_remove_link(&d->kobj, "cache");
|
|
|
|
|
|
|
|
for_each_cache(ca, d->c, i)
|
|
|
|
bd_unlink_disk_holder(ca->bdev, d->disk);
|
|
|
|
}
|
2013-02-01 23:29:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void bcache_device_link(struct bcache_device *d, struct cache_set *c,
|
|
|
|
const char *name)
|
|
|
|
{
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-02-01 23:29:41 +08:00
|
|
|
struct cache *ca;
|
|
|
|
|
|
|
|
for_each_cache(ca, d->c, i)
|
|
|
|
bd_link_disk_holder(ca->bdev, d->disk);
|
|
|
|
|
|
|
|
snprintf(d->name, BCACHEDEVNAME_SIZE,
|
|
|
|
"%s%u", name, d->id);
|
|
|
|
|
|
|
|
WARN(sysfs_create_link(&d->kobj, &c->kobj, "cache") ||
|
|
|
|
sysfs_create_link(&c->kobj, &d->kobj, d->name),
|
|
|
|
"Couldn't create device <-> cache set symlinks");
|
2015-11-30 09:19:32 +08:00
|
|
|
|
|
|
|
clear_bit(BCACHE_DEV_UNLINK_DONE, &d->flags);
|
2013-02-01 23:29:41 +08:00
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
static void bcache_device_detach(struct bcache_device *d)
|
|
|
|
{
|
|
|
|
lockdep_assert_held(&bch_register_lock);
|
|
|
|
|
2018-08-09 15:48:49 +08:00
|
|
|
atomic_dec(&d->c->attached_dev_nr);
|
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
if (test_bit(BCACHE_DEV_DETACHING, &d->flags)) {
|
2013-03-24 07:11:31 +08:00
|
|
|
struct uuid_entry *u = d->c->uuids + d->id;
|
|
|
|
|
|
|
|
SET_UUID_FLASH_ONLY(u, 0);
|
|
|
|
memcpy(u->uuid, invalid_uuid, 16);
|
2018-07-26 12:17:41 +08:00
|
|
|
u->invalidated = cpu_to_le32((u32)ktime_get_real_seconds());
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_uuid_write(d->c);
|
|
|
|
}
|
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
bcache_device_unlink(d);
|
2013-02-01 23:29:41 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
d->c->devices[d->id] = NULL;
|
|
|
|
closure_put(&d->c->caching);
|
|
|
|
d->c = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bcache_device_attach(struct bcache_device *d, struct cache_set *c,
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int id)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
d->id = id;
|
|
|
|
d->c = c;
|
|
|
|
c->devices[id] = d;
|
|
|
|
|
2018-01-09 04:21:28 +08:00
|
|
|
if (id >= c->devices_max_used)
|
|
|
|
c->devices_max_used = id + 1;
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_get(&c->caching);
|
|
|
|
}
|
|
|
|
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
static inline int first_minor_to_idx(int first_minor)
|
|
|
|
{
|
|
|
|
return (first_minor/BCACHE_MINORS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int idx_to_first_minor(int idx)
|
|
|
|
{
|
|
|
|
return (idx * BCACHE_MINORS);
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
static void bcache_device_free(struct bcache_device *d)
|
|
|
|
{
|
|
|
|
lockdep_assert_held(&bch_register_lock);
|
|
|
|
|
|
|
|
pr_info("%s stopped", d->disk->disk_name);
|
|
|
|
|
|
|
|
if (d->c)
|
|
|
|
bcache_device_detach(d);
|
2013-05-15 15:11:26 +08:00
|
|
|
if (d->disk && d->disk->flags & GENHD_FL_UP)
|
2013-03-24 07:11:31 +08:00
|
|
|
del_gendisk(d->disk);
|
|
|
|
if (d->disk && d->disk->queue)
|
|
|
|
blk_cleanup_queue(d->disk->queue);
|
2013-07-31 16:12:02 +08:00
|
|
|
if (d->disk) {
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
ida_simple_remove(&bcache_device_idx,
|
|
|
|
first_minor_to_idx(d->disk->first_minor));
|
2013-03-24 07:11:31 +08:00
|
|
|
put_disk(d->disk);
|
2013-07-31 16:12:02 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-05-21 06:25:51 +08:00
|
|
|
bioset_exit(&d->bio_split);
|
2015-07-01 05:59:30 +08:00
|
|
|
kvfree(d->full_dirty_stripes);
|
|
|
|
kvfree(d->stripe_sectors_dirty);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
closure_debug_destroy(&d->cl);
|
|
|
|
}
|
|
|
|
|
2018-08-11 13:19:44 +08:00
|
|
|
static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
|
2013-06-05 21:21:07 +08:00
|
|
|
sector_t sectors)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
struct request_queue *q;
|
2018-03-19 08:36:33 +08:00
|
|
|
const size_t max_stripes = min_t(size_t, INT_MAX,
|
|
|
|
SIZE_MAX / sizeof(atomic_t));
|
2013-06-05 21:21:07 +08:00
|
|
|
size_t n;
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
int idx;
|
2013-06-05 21:21:07 +08:00
|
|
|
|
2013-08-17 17:13:15 +08:00
|
|
|
if (!d->stripe_size)
|
|
|
|
d->stripe_size = 1 << 31;
|
2013-06-05 21:21:07 +08:00
|
|
|
|
2013-08-17 17:13:15 +08:00
|
|
|
d->nr_stripes = DIV_ROUND_UP_ULL(sectors, d->stripe_size);
|
2013-06-05 21:21:07 +08:00
|
|
|
|
2018-03-19 08:36:33 +08:00
|
|
|
if (!d->nr_stripes || d->nr_stripes > max_stripes) {
|
2016-08-19 11:15:26 +08:00
|
|
|
pr_err("nr_stripes too large or invalid: %u (start sector beyond end of disk?)",
|
2018-08-11 13:19:44 +08:00
|
|
|
(unsigned int)d->nr_stripes);
|
2013-06-05 21:21:07 +08:00
|
|
|
return -ENOMEM;
|
2013-11-01 06:43:22 +08:00
|
|
|
}
|
2013-06-05 21:21:07 +08:00
|
|
|
|
|
|
|
n = d->nr_stripes * sizeof(atomic_t);
|
2017-05-09 06:57:37 +08:00
|
|
|
d->stripe_sectors_dirty = kvzalloc(n, GFP_KERNEL);
|
2013-06-05 21:21:07 +08:00
|
|
|
if (!d->stripe_sectors_dirty)
|
|
|
|
return -ENOMEM;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-11-01 06:43:22 +08:00
|
|
|
n = BITS_TO_LONGS(d->nr_stripes) * sizeof(unsigned long);
|
2017-05-09 06:57:37 +08:00
|
|
|
d->full_dirty_stripes = kvzalloc(n, GFP_KERNEL);
|
2013-11-01 06:43:22 +08:00
|
|
|
if (!d->full_dirty_stripes)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
idx = ida_simple_get(&bcache_device_idx, 0,
|
|
|
|
BCACHE_DEVICE_IDX_MAX, GFP_KERNEL);
|
|
|
|
if (idx < 0)
|
|
|
|
return idx;
|
2016-10-24 09:19:20 +08:00
|
|
|
|
2018-05-21 06:25:51 +08:00
|
|
|
if (bioset_init(&d->bio_split, 4, offsetof(struct bbio, bio),
|
2018-07-26 12:17:40 +08:00
|
|
|
BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
d->disk = alloc_disk(BCACHE_MINORS);
|
|
|
|
if (!d->disk)
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-06-05 21:21:07 +08:00
|
|
|
set_capacity(d->disk, sectors);
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", idx);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
d->disk->major = bcache_major;
|
bcache: rewrite multiple partitions support
Current partition support of bcache is confusing and buggy. It tries to
trace non-continuous device minor numbers by an ida bit string, and
mistakenly mixed bcache device index with minor numbers. This design
generates several negative results,
- Index of bcache device name is not consecutive under /dev/. If there are
3 bcache devices, they name will be,
/dev/bcache0, /dev/bcache16, /dev/bcache32
Only bcache code indexes bcache device name is such an interesting way.
- First minor number of each bcache device is traced by ida bit string.
One bcache device will occupy 16 bits, this is not a good idea. Indeed
only one bit is enough.
- Because minor number and bcache device index are mixed, a device index
is allocated by ida_simple_get(), but an first minor number is sent into
ida_simple_remove() to release the device. It confused original author
too.
Root cause of the above errors is, bcache code should not handle device
minor numbers at all! A standard process to support multiple partitions in
Linux kernel is,
- Device driver provides major device number, and indexes multiple device
instances.
- Device driver does not allocat nor trace device minor number, only
provides a first minor number of a given device instance, and sets how
many minor numbers (paritions) the device instance may have.
All rested stuffs are handled by block layer code, most of the details can
be found from block/{genhd, partition-generic}.c files.
This patch re-writes multiple partitions support for bcache. It makes
whole things to be more clear, and uses ida bit string in a more efficeint
way.
- Ida bit string only traces bcache device index, not minor number. For a
bcache device with 128 partitions, only one bit in ida bit string is
enough.
- Device minor number and device index are separated in concept. Device
index is used for /dev node naming, and ida bit string trace. Minor
number is calculated from device index and only used to initialize
first_minor of a bcache device.
- It does not follow any standard for 16 partitions on a bcache device.
This patch sets 128 partitions on single bcache device at max, this is
the limitation from GPT (GUID Partition Table) and supported by fdisk.
Considering a typical device minor number is 20 bits width, each bcache
device may have 128 partitions (7 bits), there can be 8192 bcache devices
existing on system. For most common deployment for a single server in
now days, it should be enough.
[minor spelling fixes in commit message by Michael Lyle]
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Eric Wheeler <bcache@lists.ewheeler.net>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-10-14 07:35:31 +08:00
|
|
|
d->disk->first_minor = idx_to_first_minor(idx);
|
2013-03-24 07:11:31 +08:00
|
|
|
d->disk->fops = &bcache_ops;
|
|
|
|
d->disk->private_data = d;
|
|
|
|
|
2013-07-31 16:12:02 +08:00
|
|
|
q = blk_alloc_queue(GFP_KERNEL);
|
|
|
|
if (!q)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
blk_queue_make_request(q, NULL);
|
|
|
|
d->disk->queue = q;
|
|
|
|
q->queuedata = d;
|
2017-02-02 22:56:50 +08:00
|
|
|
q->backing_dev_info->congested_data = d;
|
2013-03-24 07:11:31 +08:00
|
|
|
q->limits.max_hw_sectors = UINT_MAX;
|
|
|
|
q->limits.max_sectors = UINT_MAX;
|
|
|
|
q->limits.max_segment_size = UINT_MAX;
|
|
|
|
q->limits.max_segments = BIO_MAX_PAGES;
|
2015-07-14 22:15:12 +08:00
|
|
|
blk_queue_max_discard_sectors(q, UINT_MAX);
|
2014-02-11 09:26:40 +08:00
|
|
|
q->limits.discard_granularity = 512;
|
2013-03-24 07:11:31 +08:00
|
|
|
q->limits.io_min = block_size;
|
|
|
|
q->limits.logical_block_size = block_size;
|
|
|
|
q->limits.physical_block_size = block_size;
|
2018-03-08 09:10:07 +08:00
|
|
|
blk_queue_flag_set(QUEUE_FLAG_NONROT, d->disk->queue);
|
|
|
|
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, d->disk->queue);
|
|
|
|
blk_queue_flag_set(QUEUE_FLAG_DISCARD, d->disk->queue);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2016-03-31 00:13:22 +08:00
|
|
|
blk_queue_write_cache(q, true, true);
|
2013-07-11 09:44:40 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
return 0;
|
2018-07-26 12:17:40 +08:00
|
|
|
|
|
|
|
err:
|
|
|
|
ida_simple_remove(&bcache_device_idx, idx);
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Cached device */
|
|
|
|
|
|
|
|
static void calc_cached_dev_sectors(struct cache_set *c)
|
|
|
|
{
|
|
|
|
uint64_t sectors = 0;
|
|
|
|
struct cached_dev *dc;
|
|
|
|
|
|
|
|
list_for_each_entry(dc, &c->cached_devs, list)
|
|
|
|
sectors += bdev_sectors(dc->bdev);
|
|
|
|
|
|
|
|
c->cached_dev_sectors = sectors;
|
|
|
|
}
|
|
|
|
|
bcache: stop bcache device when backing device is offline
Currently bcache does not handle backing device failure, if backing
device is offline and disconnected from system, its bcache device can still
be accessible. If the bcache device is in writeback mode, I/O requests even
can success if the requests hit on cache device. That is to say, when and
how bcache handles offline backing device is undefined.
This patch tries to handle backing device offline in a rather simple way,
- Add cached_dev->status_update_thread kernel thread to update backing
device status in every 1 second.
- Add cached_dev->offline_seconds to record how many seconds the backing
device is observed to be offline. If the backing device is offline for
BACKING_DEV_OFFLINE_TIMEOUT (30) seconds, set dc->io_disable to 1 and
call bcache_device_stop() to stop the bache device which linked to the
offline backing device.
Now if a backing device is offline for BACKING_DEV_OFFLINE_TIMEOUT seconds,
its bcache device will be removed, then user space application writing on
it will get error immediately, and handler the device failure in time.
This patch is quite simple, does not handle more complicated situations.
Once the bcache device is stopped, users need to recovery the backing
device, register and attach it manually.
Changelog:
v3: call wait_for_kthread_stop() before exits kernel thread.
v2: remove "bcache: " prefix when calling pr_warn().
v1: initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-05-28 15:37:41 +08:00
|
|
|
#define BACKING_DEV_OFFLINE_TIMEOUT 5
|
|
|
|
static int cached_dev_status_update(void *arg)
|
|
|
|
{
|
|
|
|
struct cached_dev *dc = arg;
|
|
|
|
struct request_queue *q;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this delayed worker is stopping outside, directly quit here.
|
|
|
|
* dc->io_disable might be set via sysfs interface, so check it
|
|
|
|
* here too.
|
|
|
|
*/
|
|
|
|
while (!kthread_should_stop() && !dc->io_disable) {
|
|
|
|
q = bdev_get_queue(dc->bdev);
|
|
|
|
if (blk_queue_dying(q))
|
|
|
|
dc->offline_seconds++;
|
|
|
|
else
|
|
|
|
dc->offline_seconds = 0;
|
|
|
|
|
|
|
|
if (dc->offline_seconds >= BACKING_DEV_OFFLINE_TIMEOUT) {
|
|
|
|
pr_err("%s: device offline for %d seconds",
|
|
|
|
dc->backing_dev_name,
|
|
|
|
BACKING_DEV_OFFLINE_TIMEOUT);
|
|
|
|
pr_err("%s: disable I/O request due to backing "
|
|
|
|
"device offline", dc->disk.name);
|
|
|
|
dc->io_disable = true;
|
|
|
|
/* let others know earlier that io_disable is true */
|
|
|
|
smp_mb();
|
|
|
|
bcache_device_stop(&dc->disk);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
schedule_timeout_interruptible(HZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
wait_for_kthread_stop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
void bch_cached_dev_run(struct cached_dev *dc)
|
|
|
|
{
|
|
|
|
struct bcache_device *d = &dc->disk;
|
2019-04-25 00:48:29 +08:00
|
|
|
char *buf = kmemdup_nul(dc->sb.label, SB_LABEL_SIZE, GFP_KERNEL);
|
2013-06-08 05:27:01 +08:00
|
|
|
char *env[] = {
|
|
|
|
"DRIVER=bcache",
|
|
|
|
kasprintf(GFP_KERNEL, "CACHED_UUID=%pU", dc->sb.uuid),
|
2019-04-25 00:48:29 +08:00
|
|
|
kasprintf(GFP_KERNEL, "CACHED_LABEL=%s", buf ? : ""),
|
2013-06-09 06:54:48 +08:00
|
|
|
NULL,
|
2013-06-08 05:27:01 +08:00
|
|
|
};
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2015-11-30 09:20:59 +08:00
|
|
|
if (atomic_xchg(&dc->running, 1)) {
|
|
|
|
kfree(env[1]);
|
|
|
|
kfree(env[2]);
|
2019-04-25 00:48:29 +08:00
|
|
|
kfree(buf);
|
2013-03-24 07:11:31 +08:00
|
|
|
return;
|
2015-11-30 09:20:59 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
if (!d->c &&
|
|
|
|
BDEV_STATE(&dc->sb) != BDEV_STATE_NONE) {
|
|
|
|
struct closure cl;
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_init_stack(&cl);
|
|
|
|
|
|
|
|
SET_BDEV_STATE(&dc->sb, BDEV_STATE_STALE);
|
|
|
|
bch_write_bdev_super(dc, &cl);
|
|
|
|
closure_sync(&cl);
|
|
|
|
}
|
|
|
|
|
|
|
|
add_disk(d->disk);
|
2013-02-01 23:29:41 +08:00
|
|
|
bd_link_disk_holder(dc->bdev, dc->disk.disk);
|
2018-08-11 13:19:55 +08:00
|
|
|
/*
|
|
|
|
* won't show up in the uevent file, use udevadm monitor -e instead
|
|
|
|
* only class / kset properties are persistent
|
|
|
|
*/
|
2013-03-24 07:11:31 +08:00
|
|
|
kobject_uevent_env(&disk_to_dev(d->disk)->kobj, KOBJ_CHANGE, env);
|
2013-06-08 05:27:01 +08:00
|
|
|
kfree(env[1]);
|
2013-06-09 06:54:48 +08:00
|
|
|
kfree(env[2]);
|
2019-04-25 00:48:29 +08:00
|
|
|
kfree(buf);
|
2013-06-08 05:27:01 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
if (sysfs_create_link(&d->kobj, &disk_to_dev(d->disk)->kobj, "dev") ||
|
|
|
|
sysfs_create_link(&disk_to_dev(d->disk)->kobj, &d->kobj, "bcache"))
|
|
|
|
pr_debug("error creating sysfs link");
|
bcache: stop bcache device when backing device is offline
Currently bcache does not handle backing device failure, if backing
device is offline and disconnected from system, its bcache device can still
be accessible. If the bcache device is in writeback mode, I/O requests even
can success if the requests hit on cache device. That is to say, when and
how bcache handles offline backing device is undefined.
This patch tries to handle backing device offline in a rather simple way,
- Add cached_dev->status_update_thread kernel thread to update backing
device status in every 1 second.
- Add cached_dev->offline_seconds to record how many seconds the backing
device is observed to be offline. If the backing device is offline for
BACKING_DEV_OFFLINE_TIMEOUT (30) seconds, set dc->io_disable to 1 and
call bcache_device_stop() to stop the bache device which linked to the
offline backing device.
Now if a backing device is offline for BACKING_DEV_OFFLINE_TIMEOUT seconds,
its bcache device will be removed, then user space application writing on
it will get error immediately, and handler the device failure in time.
This patch is quite simple, does not handle more complicated situations.
Once the bcache device is stopped, users need to recovery the backing
device, register and attach it manually.
Changelog:
v3: call wait_for_kthread_stop() before exits kernel thread.
v2: remove "bcache: " prefix when calling pr_warn().
v1: initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-05-28 15:37:41 +08:00
|
|
|
|
|
|
|
dc->status_update_thread = kthread_run(cached_dev_status_update,
|
|
|
|
dc, "bcache_status_update");
|
|
|
|
if (IS_ERR(dc->status_update_thread)) {
|
|
|
|
pr_warn("failed to create bcache_status_update kthread, "
|
|
|
|
"continue to run without monitoring backing "
|
|
|
|
"device status");
|
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
bcache: stop dc->writeback_rate_update properly
struct delayed_work writeback_rate_update in struct cache_dev is a delayed
worker to call function update_writeback_rate() in period (the interval is
defined by dc->writeback_rate_update_seconds).
When a metadate I/O error happens on cache device, bcache error handling
routine bch_cache_set_error() will call bch_cache_set_unregister() to
retire whole cache set. On the unregister code path, this delayed work is
stopped by calling cancel_delayed_work_sync(&dc->writeback_rate_update).
dc->writeback_rate_update is a special delayed work from others in bcache.
In its routine update_writeback_rate(), this delayed work is re-armed
itself. That means when cancel_delayed_work_sync() returns, this delayed
work can still be executed after several seconds defined by
dc->writeback_rate_update_seconds.
The problem is, after cancel_delayed_work_sync() returns, the cache set
unregister code path will continue and release memory of struct cache set.
Then the delayed work is scheduled to run, __update_writeback_rate()
will reference the already released cache_set memory, and trigger a NULL
pointer deference fault.
This patch introduces two more bcache device flags,
- BCACHE_DEV_WB_RUNNING
bit set: bcache device is in writeback mode and running, it is OK for
dc->writeback_rate_update to re-arm itself.
bit clear:bcache device is trying to stop dc->writeback_rate_update,
this delayed work should not re-arm itself and quit.
- BCACHE_DEV_RATE_DW_RUNNING
bit set: routine update_writeback_rate() is executing.
bit clear: routine update_writeback_rate() quits.
This patch also adds a function cancel_writeback_rate_update_dwork() to
wait for dc->writeback_rate_update quits before cancel it by calling
cancel_delayed_work_sync(). In order to avoid a deadlock by unexpected
quit dc->writeback_rate_update, after time_out seconds this function will
give up and continue to call cancel_delayed_work_sync().
And here I explain how this patch stops self re-armed delayed work properly
with the above stuffs.
update_writeback_rate() sets BCACHE_DEV_RATE_DW_RUNNING at its beginning
and clears BCACHE_DEV_RATE_DW_RUNNING at its end. Before calling
cancel_writeback_rate_update_dwork() clear flag BCACHE_DEV_WB_RUNNING.
Before calling cancel_delayed_work_sync() wait utill flag
BCACHE_DEV_RATE_DW_RUNNING is clear. So when calling
cancel_delayed_work_sync(), dc->writeback_rate_update must be already re-
armed, or quite by seeing BCACHE_DEV_WB_RUNNING cleared. In both cases
delayed work routine update_writeback_rate() won't be executed after
cancel_delayed_work_sync() returns.
Inside update_writeback_rate() before calling schedule_delayed_work(), flag
BCACHE_DEV_WB_RUNNING is checked before. If this flag is cleared, it means
someone is about to stop the delayed work. Because flag
BCACHE_DEV_RATE_DW_RUNNING is set already and cancel_delayed_work_sync()
has to wait for this flag to be cleared, we don't need to worry about race
condition here.
If update_writeback_rate() is scheduled to run after checking
BCACHE_DEV_RATE_DW_RUNNING and before calling cancel_delayed_work_sync()
in cancel_writeback_rate_update_dwork(), it is also safe. Because at this
moment BCACHE_DEV_WB_RUNNING is cleared with memory barrier. As I mentioned
previously, update_writeback_rate() will see BCACHE_DEV_WB_RUNNING is clear
and quit immediately.
Because there are more dependences inside update_writeback_rate() to struct
cache_set memory, dc->writeback_rate_update is not a simple self re-arm
delayed work. After trying many different methods (e.g. hold dc->count, or
use locks), this is the only way I can find which works to properly stop
dc->writeback_rate_update delayed work.
Changelog:
v3: change values of BCACHE_DEV_WB_RUNNING and BCACHE_DEV_RATE_DW_RUNNING
to bit index, for test_bit().
v2: Try to fix the race issue which is pointed out by Junhui.
v1: The initial version for review
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:16 +08:00
|
|
|
/*
|
|
|
|
* If BCACHE_DEV_RATE_DW_RUNNING is set, it means routine of the delayed
|
|
|
|
* work dc->writeback_rate_update is running. Wait until the routine
|
|
|
|
* quits (BCACHE_DEV_RATE_DW_RUNNING is clear), then continue to
|
|
|
|
* cancel it. If BCACHE_DEV_RATE_DW_RUNNING is not clear after time_out
|
|
|
|
* seconds, give up waiting here and continue to cancel it too.
|
|
|
|
*/
|
|
|
|
static void cancel_writeback_rate_update_dwork(struct cached_dev *dc)
|
|
|
|
{
|
|
|
|
int time_out = WRITEBACK_RATE_UPDATE_SECS_MAX * HZ;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (!test_bit(BCACHE_DEV_RATE_DW_RUNNING,
|
|
|
|
&dc->disk.flags))
|
|
|
|
break;
|
|
|
|
time_out--;
|
|
|
|
schedule_timeout_interruptible(1);
|
|
|
|
} while (time_out > 0);
|
|
|
|
|
|
|
|
if (time_out == 0)
|
|
|
|
pr_warn("give up waiting for dc->writeback_write_update to quit");
|
|
|
|
|
|
|
|
cancel_delayed_work_sync(&dc->writeback_rate_update);
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
static void cached_dev_detach_finish(struct work_struct *w)
|
|
|
|
{
|
|
|
|
struct cached_dev *dc = container_of(w, struct cached_dev, detach);
|
|
|
|
struct closure cl;
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_init_stack(&cl);
|
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
BUG_ON(!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags));
|
2017-10-31 05:46:32 +08:00
|
|
|
BUG_ON(refcount_read(&dc->count));
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
mutex_lock(&bch_register_lock);
|
|
|
|
|
bcache: stop dc->writeback_rate_update properly
struct delayed_work writeback_rate_update in struct cache_dev is a delayed
worker to call function update_writeback_rate() in period (the interval is
defined by dc->writeback_rate_update_seconds).
When a metadate I/O error happens on cache device, bcache error handling
routine bch_cache_set_error() will call bch_cache_set_unregister() to
retire whole cache set. On the unregister code path, this delayed work is
stopped by calling cancel_delayed_work_sync(&dc->writeback_rate_update).
dc->writeback_rate_update is a special delayed work from others in bcache.
In its routine update_writeback_rate(), this delayed work is re-armed
itself. That means when cancel_delayed_work_sync() returns, this delayed
work can still be executed after several seconds defined by
dc->writeback_rate_update_seconds.
The problem is, after cancel_delayed_work_sync() returns, the cache set
unregister code path will continue and release memory of struct cache set.
Then the delayed work is scheduled to run, __update_writeback_rate()
will reference the already released cache_set memory, and trigger a NULL
pointer deference fault.
This patch introduces two more bcache device flags,
- BCACHE_DEV_WB_RUNNING
bit set: bcache device is in writeback mode and running, it is OK for
dc->writeback_rate_update to re-arm itself.
bit clear:bcache device is trying to stop dc->writeback_rate_update,
this delayed work should not re-arm itself and quit.
- BCACHE_DEV_RATE_DW_RUNNING
bit set: routine update_writeback_rate() is executing.
bit clear: routine update_writeback_rate() quits.
This patch also adds a function cancel_writeback_rate_update_dwork() to
wait for dc->writeback_rate_update quits before cancel it by calling
cancel_delayed_work_sync(). In order to avoid a deadlock by unexpected
quit dc->writeback_rate_update, after time_out seconds this function will
give up and continue to call cancel_delayed_work_sync().
And here I explain how this patch stops self re-armed delayed work properly
with the above stuffs.
update_writeback_rate() sets BCACHE_DEV_RATE_DW_RUNNING at its beginning
and clears BCACHE_DEV_RATE_DW_RUNNING at its end. Before calling
cancel_writeback_rate_update_dwork() clear flag BCACHE_DEV_WB_RUNNING.
Before calling cancel_delayed_work_sync() wait utill flag
BCACHE_DEV_RATE_DW_RUNNING is clear. So when calling
cancel_delayed_work_sync(), dc->writeback_rate_update must be already re-
armed, or quite by seeing BCACHE_DEV_WB_RUNNING cleared. In both cases
delayed work routine update_writeback_rate() won't be executed after
cancel_delayed_work_sync() returns.
Inside update_writeback_rate() before calling schedule_delayed_work(), flag
BCACHE_DEV_WB_RUNNING is checked before. If this flag is cleared, it means
someone is about to stop the delayed work. Because flag
BCACHE_DEV_RATE_DW_RUNNING is set already and cancel_delayed_work_sync()
has to wait for this flag to be cleared, we don't need to worry about race
condition here.
If update_writeback_rate() is scheduled to run after checking
BCACHE_DEV_RATE_DW_RUNNING and before calling cancel_delayed_work_sync()
in cancel_writeback_rate_update_dwork(), it is also safe. Because at this
moment BCACHE_DEV_WB_RUNNING is cleared with memory barrier. As I mentioned
previously, update_writeback_rate() will see BCACHE_DEV_WB_RUNNING is clear
and quit immediately.
Because there are more dependences inside update_writeback_rate() to struct
cache_set memory, dc->writeback_rate_update is not a simple self re-arm
delayed work. After trying many different methods (e.g. hold dc->count, or
use locks), this is the only way I can find which works to properly stop
dc->writeback_rate_update delayed work.
Changelog:
v3: change values of BCACHE_DEV_WB_RUNNING and BCACHE_DEV_RATE_DW_RUNNING
to bit index, for test_bit().
v2: Try to fix the race issue which is pointed out by Junhui.
v1: The initial version for review
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:16 +08:00
|
|
|
if (test_and_clear_bit(BCACHE_DEV_WB_RUNNING, &dc->disk.flags))
|
|
|
|
cancel_writeback_rate_update_dwork(dc);
|
|
|
|
|
2018-01-09 04:21:19 +08:00
|
|
|
if (!IS_ERR_OR_NULL(dc->writeback_thread)) {
|
|
|
|
kthread_stop(dc->writeback_thread);
|
|
|
|
dc->writeback_thread = NULL;
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
memset(&dc->sb.set_uuid, 0, 16);
|
|
|
|
SET_BDEV_STATE(&dc->sb, BDEV_STATE_NONE);
|
|
|
|
|
|
|
|
bch_write_bdev_super(dc, &cl);
|
|
|
|
closure_sync(&cl);
|
|
|
|
|
2018-10-08 20:41:15 +08:00
|
|
|
calc_cached_dev_sectors(dc->disk.c);
|
2013-03-24 07:11:31 +08:00
|
|
|
bcache_device_detach(&dc->disk);
|
|
|
|
list_move(&dc->list, &uncached_devices);
|
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
clear_bit(BCACHE_DEV_DETACHING, &dc->disk.flags);
|
2014-03-20 08:49:37 +08:00
|
|
|
clear_bit(BCACHE_DEV_UNLINK_DONE, &dc->disk.flags);
|
2013-08-22 08:49:09 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_info("Caching disabled for %s", dc->backing_dev_name);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
/* Drop ref we took in cached_dev_detach() */
|
|
|
|
closure_put(&dc->disk.cl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void bch_cached_dev_detach(struct cached_dev *dc)
|
|
|
|
{
|
|
|
|
lockdep_assert_held(&bch_register_lock);
|
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
if (test_bit(BCACHE_DEV_CLOSING, &dc->disk.flags))
|
2013-03-24 07:11:31 +08:00
|
|
|
return;
|
|
|
|
|
2013-08-22 08:49:09 +08:00
|
|
|
if (test_and_set_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
|
2013-03-24 07:11:31 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Block the device from being closed and freed until we're finished
|
|
|
|
* detaching
|
|
|
|
*/
|
|
|
|
closure_get(&dc->disk.cl);
|
|
|
|
|
|
|
|
bch_writeback_queue(dc);
|
bcache: stop dc->writeback_rate_update properly
struct delayed_work writeback_rate_update in struct cache_dev is a delayed
worker to call function update_writeback_rate() in period (the interval is
defined by dc->writeback_rate_update_seconds).
When a metadate I/O error happens on cache device, bcache error handling
routine bch_cache_set_error() will call bch_cache_set_unregister() to
retire whole cache set. On the unregister code path, this delayed work is
stopped by calling cancel_delayed_work_sync(&dc->writeback_rate_update).
dc->writeback_rate_update is a special delayed work from others in bcache.
In its routine update_writeback_rate(), this delayed work is re-armed
itself. That means when cancel_delayed_work_sync() returns, this delayed
work can still be executed after several seconds defined by
dc->writeback_rate_update_seconds.
The problem is, after cancel_delayed_work_sync() returns, the cache set
unregister code path will continue and release memory of struct cache set.
Then the delayed work is scheduled to run, __update_writeback_rate()
will reference the already released cache_set memory, and trigger a NULL
pointer deference fault.
This patch introduces two more bcache device flags,
- BCACHE_DEV_WB_RUNNING
bit set: bcache device is in writeback mode and running, it is OK for
dc->writeback_rate_update to re-arm itself.
bit clear:bcache device is trying to stop dc->writeback_rate_update,
this delayed work should not re-arm itself and quit.
- BCACHE_DEV_RATE_DW_RUNNING
bit set: routine update_writeback_rate() is executing.
bit clear: routine update_writeback_rate() quits.
This patch also adds a function cancel_writeback_rate_update_dwork() to
wait for dc->writeback_rate_update quits before cancel it by calling
cancel_delayed_work_sync(). In order to avoid a deadlock by unexpected
quit dc->writeback_rate_update, after time_out seconds this function will
give up and continue to call cancel_delayed_work_sync().
And here I explain how this patch stops self re-armed delayed work properly
with the above stuffs.
update_writeback_rate() sets BCACHE_DEV_RATE_DW_RUNNING at its beginning
and clears BCACHE_DEV_RATE_DW_RUNNING at its end. Before calling
cancel_writeback_rate_update_dwork() clear flag BCACHE_DEV_WB_RUNNING.
Before calling cancel_delayed_work_sync() wait utill flag
BCACHE_DEV_RATE_DW_RUNNING is clear. So when calling
cancel_delayed_work_sync(), dc->writeback_rate_update must be already re-
armed, or quite by seeing BCACHE_DEV_WB_RUNNING cleared. In both cases
delayed work routine update_writeback_rate() won't be executed after
cancel_delayed_work_sync() returns.
Inside update_writeback_rate() before calling schedule_delayed_work(), flag
BCACHE_DEV_WB_RUNNING is checked before. If this flag is cleared, it means
someone is about to stop the delayed work. Because flag
BCACHE_DEV_RATE_DW_RUNNING is set already and cancel_delayed_work_sync()
has to wait for this flag to be cleared, we don't need to worry about race
condition here.
If update_writeback_rate() is scheduled to run after checking
BCACHE_DEV_RATE_DW_RUNNING and before calling cancel_delayed_work_sync()
in cancel_writeback_rate_update_dwork(), it is also safe. Because at this
moment BCACHE_DEV_WB_RUNNING is cleared with memory barrier. As I mentioned
previously, update_writeback_rate() will see BCACHE_DEV_WB_RUNNING is clear
and quit immediately.
Because there are more dependences inside update_writeback_rate() to struct
cache_set memory, dc->writeback_rate_update is not a simple self re-arm
delayed work. After trying many different methods (e.g. hold dc->count, or
use locks), this is the only way I can find which works to properly stop
dc->writeback_rate_update delayed work.
Changelog:
v3: change values of BCACHE_DEV_WB_RUNNING and BCACHE_DEV_RATE_DW_RUNNING
to bit index, for test_bit().
v2: Try to fix the race issue which is pointed out by Junhui.
v1: The initial version for review
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:16 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
cached_dev_put(dc);
|
|
|
|
}
|
|
|
|
|
bcache: fix for data collapse after re-attaching an attached device
back-end device sdm has already attached a cache_set with ID
f67ebe1f-f8bc-4d73-bfe5-9dc88607f119, then try to attach with
another cache set, and it returns with an error:
[root]# cd /sys/block/sdm/bcache
[root]# echo 5ccd0a63-148e-48b8-afa2-aca9cbd6279f > attach
-bash: echo: write error: Invalid argument
After that, execute a command to modify the label of bcache
device:
[root]# echo data_disk1 > label
Then we reboot the system, when the system power on, the back-end
device can not attach to cache_set, a messages show in the log:
Feb 5 12:05:52 ceph152 kernel: [922385.508498] bcache:
bch_cached_dev_attach() couldn't find uuid for sdm in set
In sysfs_attach(), dc->sb.set_uuid was assigned to the value
which input through sysfs, no matter whether it is success
or not in bch_cached_dev_attach(). For example, If the back-end
device has already attached to an cache set, bch_cached_dev_attach()
would fail, but dc->sb.set_uuid was changed. Then modify the
label of bcache device, it will call bch_write_bdev_super(),
which would write the dc->sb.set_uuid to the super block, so we
record a wrong cache set ID in the super block, after the system
reboot, the cache set couldn't find the uuid of the back-end
device, so the bcache device couldn't exist and use any more.
In this patch, we don't assigned cache set ID to dc->sb.set_uuid
in sysfs_attach() directly, but input it into bch_cached_dev_attach(),
and assigned dc->sb.set_uuid to the cache set ID after the back-end
device attached to the cache set successful.
Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-02-08 03:41:46 +08:00
|
|
|
int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
|
|
|
|
uint8_t *set_uuid)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
2018-07-26 12:17:41 +08:00
|
|
|
uint32_t rtime = cpu_to_le32((u32)ktime_get_real_seconds());
|
2013-03-24 07:11:31 +08:00
|
|
|
struct uuid_entry *u;
|
2018-03-06 05:41:55 +08:00
|
|
|
struct cached_dev *exist_dc, *t;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
bcache: fix for data collapse after re-attaching an attached device
back-end device sdm has already attached a cache_set with ID
f67ebe1f-f8bc-4d73-bfe5-9dc88607f119, then try to attach with
another cache set, and it returns with an error:
[root]# cd /sys/block/sdm/bcache
[root]# echo 5ccd0a63-148e-48b8-afa2-aca9cbd6279f > attach
-bash: echo: write error: Invalid argument
After that, execute a command to modify the label of bcache
device:
[root]# echo data_disk1 > label
Then we reboot the system, when the system power on, the back-end
device can not attach to cache_set, a messages show in the log:
Feb 5 12:05:52 ceph152 kernel: [922385.508498] bcache:
bch_cached_dev_attach() couldn't find uuid for sdm in set
In sysfs_attach(), dc->sb.set_uuid was assigned to the value
which input through sysfs, no matter whether it is success
or not in bch_cached_dev_attach(). For example, If the back-end
device has already attached to an cache set, bch_cached_dev_attach()
would fail, but dc->sb.set_uuid was changed. Then modify the
label of bcache device, it will call bch_write_bdev_super(),
which would write the dc->sb.set_uuid to the super block, so we
record a wrong cache set ID in the super block, after the system
reboot, the cache set couldn't find the uuid of the back-end
device, so the bcache device couldn't exist and use any more.
In this patch, we don't assigned cache set ID to dc->sb.set_uuid
in sysfs_attach() directly, but input it into bch_cached_dev_attach(),
and assigned dc->sb.set_uuid to the cache set ID after the back-end
device attached to the cache set successful.
Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-02-08 03:41:46 +08:00
|
|
|
if ((set_uuid && memcmp(set_uuid, c->sb.set_uuid, 16)) ||
|
|
|
|
(!set_uuid && memcmp(dc->sb.set_uuid, c->sb.set_uuid, 16)))
|
2013-03-24 07:11:31 +08:00
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
if (dc->disk.c) {
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_err("Can't attach %s: already attached",
|
|
|
|
dc->backing_dev_name);
|
2013-03-24 07:11:31 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (test_bit(CACHE_SET_STOPPING, &c->flags)) {
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_err("Can't attach %s: shutting down",
|
|
|
|
dc->backing_dev_name);
|
2013-03-24 07:11:31 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dc->sb.block_size < c->sb.block_size) {
|
|
|
|
/* Will die */
|
2013-03-26 02:46:44 +08:00
|
|
|
pr_err("Couldn't attach %s: block size less than set's block size",
|
2018-05-03 18:51:32 +08:00
|
|
|
dc->backing_dev_name);
|
2013-03-24 07:11:31 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-03-06 05:41:55 +08:00
|
|
|
/* Check whether already attached */
|
|
|
|
list_for_each_entry_safe(exist_dc, t, &c->cached_devs, list) {
|
|
|
|
if (!memcmp(dc->sb.uuid, exist_dc->sb.uuid, 16)) {
|
|
|
|
pr_err("Tried to attach %s but duplicate UUID already attached",
|
2018-05-03 18:51:32 +08:00
|
|
|
dc->backing_dev_name);
|
2018-03-06 05:41:55 +08:00
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
u = uuid_find(c, dc->sb.uuid);
|
|
|
|
|
|
|
|
if (u &&
|
|
|
|
(BDEV_STATE(&dc->sb) == BDEV_STATE_STALE ||
|
|
|
|
BDEV_STATE(&dc->sb) == BDEV_STATE_NONE)) {
|
|
|
|
memcpy(u->uuid, invalid_uuid, 16);
|
2018-07-26 12:17:41 +08:00
|
|
|
u->invalidated = cpu_to_le32((u32)ktime_get_real_seconds());
|
2013-03-24 07:11:31 +08:00
|
|
|
u = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!u) {
|
|
|
|
if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_err("Couldn't find uuid for %s in set",
|
|
|
|
dc->backing_dev_name);
|
2013-03-24 07:11:31 +08:00
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
u = uuid_find_empty(c);
|
|
|
|
if (!u) {
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_err("Not caching %s, no room for UUID",
|
|
|
|
dc->backing_dev_name);
|
2013-03-24 07:11:31 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-11 13:19:55 +08:00
|
|
|
/*
|
|
|
|
* Deadlocks since we're called via sysfs...
|
|
|
|
* sysfs_remove_file(&dc->kobj, &sysfs_attach);
|
2013-03-24 07:11:31 +08:00
|
|
|
*/
|
|
|
|
|
2013-03-29 02:50:55 +08:00
|
|
|
if (bch_is_zero(u->uuid, 16)) {
|
2013-03-24 07:11:31 +08:00
|
|
|
struct closure cl;
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_init_stack(&cl);
|
|
|
|
|
|
|
|
memcpy(u->uuid, dc->sb.uuid, 16);
|
|
|
|
memcpy(u->label, dc->sb.label, SB_LABEL_SIZE);
|
|
|
|
u->first_reg = u->last_reg = rtime;
|
|
|
|
bch_uuid_write(c);
|
|
|
|
|
|
|
|
memcpy(dc->sb.set_uuid, c->sb.set_uuid, 16);
|
|
|
|
SET_BDEV_STATE(&dc->sb, BDEV_STATE_CLEAN);
|
|
|
|
|
|
|
|
bch_write_bdev_super(dc, &cl);
|
|
|
|
closure_sync(&cl);
|
|
|
|
} else {
|
|
|
|
u->last_reg = rtime;
|
|
|
|
bch_uuid_write(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
bcache_device_attach(&dc->disk, c, u - c->uuids);
|
|
|
|
list_move(&dc->list, &c->cached_devs);
|
|
|
|
calc_cached_dev_sectors(c);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dc->c must be set before dc->count != 0 - paired with the mb in
|
|
|
|
* cached_dev_get()
|
|
|
|
*/
|
2018-08-11 13:20:00 +08:00
|
|
|
smp_wmb();
|
2017-10-31 05:46:32 +08:00
|
|
|
refcount_set(&dc->count, 1);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2016-02-27 06:39:06 +08:00
|
|
|
/* Block writeback thread, but spawn it */
|
|
|
|
down_write(&dc->writeback_lock);
|
|
|
|
if (bch_cached_dev_writeback_start(dc)) {
|
|
|
|
up_write(&dc->writeback_lock);
|
2014-05-02 04:48:57 +08:00
|
|
|
return -ENOMEM;
|
2016-02-27 06:39:06 +08:00
|
|
|
}
|
2014-05-02 04:48:57 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
|
|
|
|
atomic_set(&dc->has_dirty, 1);
|
|
|
|
bch_writeback_queue(dc);
|
|
|
|
}
|
|
|
|
|
2018-10-08 20:41:12 +08:00
|
|
|
bch_sectors_dirty_init(&dc->disk);
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_cached_dev_run(dc);
|
2013-02-01 23:29:41 +08:00
|
|
|
bcache_device_link(&dc->disk, c, "bdev");
|
2018-08-09 15:48:49 +08:00
|
|
|
atomic_inc(&c->attached_dev_nr);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2016-02-27 06:39:06 +08:00
|
|
|
/* Allow the writeback thread to proceed */
|
|
|
|
up_write(&dc->writeback_lock);
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
pr_info("Caching %s as %s on set %pU",
|
2018-05-03 18:51:32 +08:00
|
|
|
dc->backing_dev_name,
|
|
|
|
dc->disk.disk->disk_name,
|
2013-03-24 07:11:31 +08:00
|
|
|
dc->disk.c->sb.set_uuid);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-25 00:48:35 +08:00
|
|
|
/* when dc->disk.kobj released */
|
2013-03-24 07:11:31 +08:00
|
|
|
void bch_cached_dev_release(struct kobject *kobj)
|
|
|
|
{
|
|
|
|
struct cached_dev *dc = container_of(kobj, struct cached_dev,
|
|
|
|
disk.kobj);
|
|
|
|
kfree(dc);
|
|
|
|
module_put(THIS_MODULE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cached_dev_free(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
|
|
|
|
|
bcache: stop dc->writeback_rate_update properly
struct delayed_work writeback_rate_update in struct cache_dev is a delayed
worker to call function update_writeback_rate() in period (the interval is
defined by dc->writeback_rate_update_seconds).
When a metadate I/O error happens on cache device, bcache error handling
routine bch_cache_set_error() will call bch_cache_set_unregister() to
retire whole cache set. On the unregister code path, this delayed work is
stopped by calling cancel_delayed_work_sync(&dc->writeback_rate_update).
dc->writeback_rate_update is a special delayed work from others in bcache.
In its routine update_writeback_rate(), this delayed work is re-armed
itself. That means when cancel_delayed_work_sync() returns, this delayed
work can still be executed after several seconds defined by
dc->writeback_rate_update_seconds.
The problem is, after cancel_delayed_work_sync() returns, the cache set
unregister code path will continue and release memory of struct cache set.
Then the delayed work is scheduled to run, __update_writeback_rate()
will reference the already released cache_set memory, and trigger a NULL
pointer deference fault.
This patch introduces two more bcache device flags,
- BCACHE_DEV_WB_RUNNING
bit set: bcache device is in writeback mode and running, it is OK for
dc->writeback_rate_update to re-arm itself.
bit clear:bcache device is trying to stop dc->writeback_rate_update,
this delayed work should not re-arm itself and quit.
- BCACHE_DEV_RATE_DW_RUNNING
bit set: routine update_writeback_rate() is executing.
bit clear: routine update_writeback_rate() quits.
This patch also adds a function cancel_writeback_rate_update_dwork() to
wait for dc->writeback_rate_update quits before cancel it by calling
cancel_delayed_work_sync(). In order to avoid a deadlock by unexpected
quit dc->writeback_rate_update, after time_out seconds this function will
give up and continue to call cancel_delayed_work_sync().
And here I explain how this patch stops self re-armed delayed work properly
with the above stuffs.
update_writeback_rate() sets BCACHE_DEV_RATE_DW_RUNNING at its beginning
and clears BCACHE_DEV_RATE_DW_RUNNING at its end. Before calling
cancel_writeback_rate_update_dwork() clear flag BCACHE_DEV_WB_RUNNING.
Before calling cancel_delayed_work_sync() wait utill flag
BCACHE_DEV_RATE_DW_RUNNING is clear. So when calling
cancel_delayed_work_sync(), dc->writeback_rate_update must be already re-
armed, or quite by seeing BCACHE_DEV_WB_RUNNING cleared. In both cases
delayed work routine update_writeback_rate() won't be executed after
cancel_delayed_work_sync() returns.
Inside update_writeback_rate() before calling schedule_delayed_work(), flag
BCACHE_DEV_WB_RUNNING is checked before. If this flag is cleared, it means
someone is about to stop the delayed work. Because flag
BCACHE_DEV_RATE_DW_RUNNING is set already and cancel_delayed_work_sync()
has to wait for this flag to be cleared, we don't need to worry about race
condition here.
If update_writeback_rate() is scheduled to run after checking
BCACHE_DEV_RATE_DW_RUNNING and before calling cancel_delayed_work_sync()
in cancel_writeback_rate_update_dwork(), it is also safe. Because at this
moment BCACHE_DEV_WB_RUNNING is cleared with memory barrier. As I mentioned
previously, update_writeback_rate() will see BCACHE_DEV_WB_RUNNING is clear
and quit immediately.
Because there are more dependences inside update_writeback_rate() to struct
cache_set memory, dc->writeback_rate_update is not a simple self re-arm
delayed work. After trying many different methods (e.g. hold dc->count, or
use locks), this is the only way I can find which works to properly stop
dc->writeback_rate_update delayed work.
Changelog:
v3: change values of BCACHE_DEV_WB_RUNNING and BCACHE_DEV_RATE_DW_RUNNING
to bit index, for test_bit().
v2: Try to fix the race issue which is pointed out by Junhui.
v1: The initial version for review
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Junhui Tang <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:16 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
|
|
|
|
|
|
|
if (test_and_clear_bit(BCACHE_DEV_WB_RUNNING, &dc->disk.flags))
|
|
|
|
cancel_writeback_rate_update_dwork(dc);
|
|
|
|
|
2014-05-21 03:20:28 +08:00
|
|
|
if (!IS_ERR_OR_NULL(dc->writeback_thread))
|
|
|
|
kthread_stop(dc->writeback_thread);
|
2017-09-06 14:25:59 +08:00
|
|
|
if (dc->writeback_write_wq)
|
|
|
|
destroy_workqueue(dc->writeback_write_wq);
|
bcache: stop bcache device when backing device is offline
Currently bcache does not handle backing device failure, if backing
device is offline and disconnected from system, its bcache device can still
be accessible. If the bcache device is in writeback mode, I/O requests even
can success if the requests hit on cache device. That is to say, when and
how bcache handles offline backing device is undefined.
This patch tries to handle backing device offline in a rather simple way,
- Add cached_dev->status_update_thread kernel thread to update backing
device status in every 1 second.
- Add cached_dev->offline_seconds to record how many seconds the backing
device is observed to be offline. If the backing device is offline for
BACKING_DEV_OFFLINE_TIMEOUT (30) seconds, set dc->io_disable to 1 and
call bcache_device_stop() to stop the bache device which linked to the
offline backing device.
Now if a backing device is offline for BACKING_DEV_OFFLINE_TIMEOUT seconds,
its bcache device will be removed, then user space application writing on
it will get error immediately, and handler the device failure in time.
This patch is quite simple, does not handle more complicated situations.
Once the bcache device is stopped, users need to recovery the backing
device, register and attach it manually.
Changelog:
v3: call wait_for_kthread_stop() before exits kernel thread.
v2: remove "bcache: " prefix when calling pr_warn().
v1: initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-05-28 15:37:41 +08:00
|
|
|
if (!IS_ERR_OR_NULL(dc->status_update_thread))
|
|
|
|
kthread_stop(dc->status_update_thread);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-05-15 15:11:26 +08:00
|
|
|
if (atomic_read(&dc->running))
|
|
|
|
bd_unlink_disk_holder(dc->bdev, dc->disk.disk);
|
2013-03-24 07:11:31 +08:00
|
|
|
bcache_device_free(&dc->disk);
|
|
|
|
list_del(&dc->list);
|
|
|
|
|
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
|
2014-07-08 04:03:36 +08:00
|
|
|
if (!IS_ERR_OR_NULL(dc->bdev))
|
2013-03-24 07:11:31 +08:00
|
|
|
blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
|
|
|
|
|
|
|
|
wake_up(&unregister_wait);
|
|
|
|
|
|
|
|
kobject_put(&dc->disk.kobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cached_dev_flush(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
|
|
|
|
struct bcache_device *d = &dc->disk;
|
|
|
|
|
2013-07-11 12:25:02 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2013-08-22 08:49:09 +08:00
|
|
|
bcache_device_unlink(d);
|
2013-07-11 12:25:02 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_cache_accounting_destroy(&dc->accounting);
|
|
|
|
kobject_del(&d->kobj);
|
|
|
|
|
|
|
|
continue_at(cl, cached_dev_free, system_wq);
|
|
|
|
}
|
|
|
|
|
2018-08-11 13:19:44 +08:00
|
|
|
static int cached_dev_init(struct cached_dev *dc, unsigned int block_size)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
2013-05-15 15:11:26 +08:00
|
|
|
int ret;
|
2013-03-24 07:11:31 +08:00
|
|
|
struct io *io;
|
2013-05-15 15:11:26 +08:00
|
|
|
struct request_queue *q = bdev_get_queue(dc->bdev);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
__module_get(THIS_MODULE);
|
|
|
|
INIT_LIST_HEAD(&dc->list);
|
2013-05-15 15:11:26 +08:00
|
|
|
closure_init(&dc->disk.cl, NULL);
|
|
|
|
set_closure_fn(&dc->disk.cl, cached_dev_flush, system_wq);
|
2013-03-24 07:11:31 +08:00
|
|
|
kobject_init(&dc->disk.kobj, &bch_cached_dev_ktype);
|
|
|
|
INIT_WORK(&dc->detach, cached_dev_detach_finish);
|
2013-12-17 07:27:25 +08:00
|
|
|
sema_init(&dc->sb_write_mutex, 1);
|
2013-05-15 15:11:26 +08:00
|
|
|
INIT_LIST_HEAD(&dc->io_lru);
|
|
|
|
spin_lock_init(&dc->io_lock);
|
|
|
|
bch_cache_accounting_init(&dc->accounting, &dc->disk.cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
dc->sequential_cutoff = 4 << 20;
|
|
|
|
|
|
|
|
for (io = dc->io; io < dc->io + RECENT_IO; io++) {
|
|
|
|
list_add(&io->lru, &dc->io_lru);
|
|
|
|
hlist_add_head(&io->hash, dc->io_hash + RECENT_IO);
|
|
|
|
}
|
|
|
|
|
2013-07-12 13:39:53 +08:00
|
|
|
dc->disk.stripe_size = q->limits.io_opt >> 9;
|
|
|
|
|
|
|
|
if (dc->disk.stripe_size)
|
|
|
|
dc->partial_stripes_expensive =
|
|
|
|
q->limits.raid_partial_stripes_expensive;
|
|
|
|
|
2013-06-05 21:21:07 +08:00
|
|
|
ret = bcache_device_init(&dc->disk, block_size,
|
|
|
|
dc->bdev->bd_part->nr_sects - dc->sb.data_offset);
|
2013-05-15 15:11:26 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2017-02-02 22:56:50 +08:00
|
|
|
dc->disk.disk->queue->backing_dev_info->ra_pages =
|
|
|
|
max(dc->disk.disk->queue->backing_dev_info->ra_pages,
|
|
|
|
q->backing_dev_info->ra_pages);
|
2013-05-15 15:11:26 +08:00
|
|
|
|
bcache: add io_disable to struct cached_dev
If a bcache device is configured to writeback mode, current code does not
handle write I/O errors on backing devices properly.
In writeback mode, write request is written to cache device, and
latter being flushed to backing device. If I/O failed when writing from
cache device to the backing device, bcache code just ignores the error and
upper layer code is NOT noticed that the backing device is broken.
This patch tries to handle backing device failure like how the cache device
failure is handled,
- Add a error counter 'io_errors' and error limit 'error_limit' in struct
cached_dev. Add another io_disable to struct cached_dev to disable I/Os
on the problematic backing device.
- When I/O error happens on backing device, increase io_errors counter. And
if io_errors reaches error_limit, set cache_dev->io_disable to true, and
stop the bcache device.
The result is, if backing device is broken of disconnected, and I/O errors
reach its error limit, backing device will be disabled and the associated
bcache device will be removed from system.
Changelog:
v2: remove "bcache: " prefix in pr_error(), and use correct name string to
print out bcache device gendisk name.
v1: indeed this is new added in v2 patch set.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:25 +08:00
|
|
|
atomic_set(&dc->io_errors, 0);
|
|
|
|
dc->io_disable = false;
|
|
|
|
dc->error_limit = DEFAULT_CACHED_DEV_ERROR_LIMIT;
|
bcache: add stop_when_cache_set_failed option to backing device
When there are too many I/O errors on cache device, current bcache code
will retire the whole cache set, and detach all bcache devices. But the
detached bcache devices are not stopped, which is problematic when bcache
is in writeback mode.
If the retired cache set has dirty data of backing devices, continue
writing to bcache device will write to backing device directly. If the
LBA of write request has a dirty version cached on cache device, next time
when the cache device is re-registered and backing device re-attached to
it again, the stale dirty data on cache device will be written to backing
device, and overwrite latest directly written data. This situation causes
a quite data corruption.
But we cannot simply stop all attached bcache devices when the cache set is
broken or disconnected. For example, use bcache to accelerate performance
of an email service. In such workload, if cache device is broken but no
dirty data lost, keep the bcache device alive and permit email service
continue to access user data might be a better solution for the cache
device failure.
Nix <nix@esperi.org.uk> points out the issue and provides the above example
to explain why it might be necessary to not stop bcache device for broken
cache device. Pavel Goran <via-bcache@pvgoran.name> provides a brilliant
suggestion to provide "always" and "auto" options to per-cached device
sysfs file stop_when_cache_set_failed. If cache set is retiring and the
backing device has no dirty data on cache, it should be safe to keep the
bcache device alive. In this case, if stop_when_cache_set_failed is set to
"auto", the device failure handling code will not stop this bcache device
and permit application to access the backing device with a unattached
bcache device.
Changelog:
[mlyle: edited to not break string constants across lines]
v3: fix typos pointed out by Nix.
v2: change option values of stop_when_cache_set_failed from 1/0 to
"auto"/"always".
v1: initial version, stop_when_cache_set_failed can be 0 (not stop) or 1
(always stop).
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Cc: Nix <nix@esperi.org.uk>
Cc: Pavel Goran <via-bcache@pvgoran.name>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:18 +08:00
|
|
|
/* default to auto */
|
|
|
|
dc->stop_when_cache_set_failed = BCH_CACHED_DEV_STOP_AUTO;
|
|
|
|
|
2013-05-15 15:11:26 +08:00
|
|
|
bch_cached_dev_request_init(dc);
|
|
|
|
bch_cached_dev_writeback_init(dc);
|
2013-03-24 07:11:31 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cached device - bcache superblock */
|
|
|
|
|
2019-04-25 00:48:37 +08:00
|
|
|
static int register_bdev(struct cache_sb *sb, struct page *sb_page,
|
2013-03-24 07:11:31 +08:00
|
|
|
struct block_device *bdev,
|
|
|
|
struct cached_dev *dc)
|
|
|
|
{
|
|
|
|
const char *err = "cannot allocate memory";
|
|
|
|
struct cache_set *c;
|
|
|
|
|
2018-05-03 18:51:32 +08:00
|
|
|
bdevname(bdev, dc->backing_dev_name);
|
2013-03-24 07:11:31 +08:00
|
|
|
memcpy(&dc->sb, sb, sizeof(struct cache_sb));
|
|
|
|
dc->bdev = bdev;
|
|
|
|
dc->bdev->bd_holder = dc;
|
|
|
|
|
2016-11-22 23:57:21 +08:00
|
|
|
bio_init(&dc->sb_bio, dc->sb_bio.bi_inline_vecs, 1);
|
2017-12-18 20:22:04 +08:00
|
|
|
bio_first_bvec_all(&dc->sb_bio)->bv_page = sb_page;
|
2013-05-15 15:11:26 +08:00
|
|
|
get_page(sb_page);
|
2013-03-28 02:09:23 +08:00
|
|
|
|
2018-05-03 18:51:32 +08:00
|
|
|
|
2013-05-15 15:11:26 +08:00
|
|
|
if (cached_dev_init(dc, sb->block_size << 9))
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
err = "error creating kobject";
|
|
|
|
if (kobject_add(&dc->disk.kobj, &part_to_dev(bdev->bd_part)->kobj,
|
|
|
|
"bcache"))
|
|
|
|
goto err;
|
|
|
|
if (bch_cache_accounting_add_kobjs(&dc->accounting, &dc->disk.kobj))
|
|
|
|
goto err;
|
|
|
|
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_info("registered backing device %s", dc->backing_dev_name);
|
2013-05-15 15:11:26 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
list_add(&dc->list, &uncached_devices);
|
2018-08-09 15:48:45 +08:00
|
|
|
/* attach to a matched cache set if it exists */
|
2013-03-24 07:11:31 +08:00
|
|
|
list_for_each_entry(c, &bch_cache_sets, list)
|
bcache: fix for data collapse after re-attaching an attached device
back-end device sdm has already attached a cache_set with ID
f67ebe1f-f8bc-4d73-bfe5-9dc88607f119, then try to attach with
another cache set, and it returns with an error:
[root]# cd /sys/block/sdm/bcache
[root]# echo 5ccd0a63-148e-48b8-afa2-aca9cbd6279f > attach
-bash: echo: write error: Invalid argument
After that, execute a command to modify the label of bcache
device:
[root]# echo data_disk1 > label
Then we reboot the system, when the system power on, the back-end
device can not attach to cache_set, a messages show in the log:
Feb 5 12:05:52 ceph152 kernel: [922385.508498] bcache:
bch_cached_dev_attach() couldn't find uuid for sdm in set
In sysfs_attach(), dc->sb.set_uuid was assigned to the value
which input through sysfs, no matter whether it is success
or not in bch_cached_dev_attach(). For example, If the back-end
device has already attached to an cache set, bch_cached_dev_attach()
would fail, but dc->sb.set_uuid was changed. Then modify the
label of bcache device, it will call bch_write_bdev_super(),
which would write the dc->sb.set_uuid to the super block, so we
record a wrong cache set ID in the super block, after the system
reboot, the cache set couldn't find the uuid of the back-end
device, so the bcache device couldn't exist and use any more.
In this patch, we don't assigned cache set ID to dc->sb.set_uuid
in sysfs_attach() directly, but input it into bch_cached_dev_attach(),
and assigned dc->sb.set_uuid to the cache set ID after the back-end
device attached to the cache set successful.
Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-02-08 03:41:46 +08:00
|
|
|
bch_cached_dev_attach(dc, c, NULL);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
if (BDEV_STATE(&dc->sb) == BDEV_STATE_NONE ||
|
|
|
|
BDEV_STATE(&dc->sb) == BDEV_STATE_STALE)
|
|
|
|
bch_cached_dev_run(dc);
|
|
|
|
|
2019-04-25 00:48:37 +08:00
|
|
|
return 0;
|
2013-03-24 07:11:31 +08:00
|
|
|
err:
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_notice("error %s: %s", dc->backing_dev_name, err);
|
2013-05-15 15:11:26 +08:00
|
|
|
bcache_device_stop(&dc->disk);
|
2019-04-25 00:48:37 +08:00
|
|
|
return -EIO;
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Flash only volumes */
|
|
|
|
|
2019-04-25 00:48:35 +08:00
|
|
|
/* When d->kobj released */
|
2013-03-24 07:11:31 +08:00
|
|
|
void bch_flash_dev_release(struct kobject *kobj)
|
|
|
|
{
|
|
|
|
struct bcache_device *d = container_of(kobj, struct bcache_device,
|
|
|
|
kobj);
|
|
|
|
kfree(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void flash_dev_free(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct bcache_device *d = container_of(cl, struct bcache_device, cl);
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2014-04-30 06:39:27 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2018-07-26 12:17:33 +08:00
|
|
|
atomic_long_sub(bcache_dev_sectors_dirty(d),
|
|
|
|
&d->c->flash_dev_dirty_sectors);
|
2013-03-24 07:11:31 +08:00
|
|
|
bcache_device_free(d);
|
2014-04-30 06:39:27 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
kobject_put(&d->kobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void flash_dev_flush(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct bcache_device *d = container_of(cl, struct bcache_device, cl);
|
|
|
|
|
2014-04-30 06:39:27 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2013-02-01 23:29:41 +08:00
|
|
|
bcache_device_unlink(d);
|
2014-04-30 06:39:27 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
kobject_del(&d->kobj);
|
|
|
|
continue_at(cl, flash_dev_free, system_wq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
|
|
|
|
{
|
|
|
|
struct bcache_device *d = kzalloc(sizeof(struct bcache_device),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!d)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
closure_init(&d->cl, NULL);
|
|
|
|
set_closure_fn(&d->cl, flash_dev_flush, system_wq);
|
|
|
|
|
|
|
|
kobject_init(&d->kobj, &bch_flash_dev_ktype);
|
|
|
|
|
2013-06-05 21:21:07 +08:00
|
|
|
if (bcache_device_init(d, block_bytes(c), u->sectors))
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
bcache_device_attach(d, c, u - c->uuids);
|
2017-09-07 01:28:53 +08:00
|
|
|
bch_sectors_dirty_init(d);
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_flash_dev_request_init(d);
|
|
|
|
add_disk(d->disk);
|
|
|
|
|
|
|
|
if (kobject_add(&d->kobj, &disk_to_dev(d->disk)->kobj, "bcache"))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
bcache_device_link(d, c, "volume");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
kobject_put(&d->kobj);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int flash_devs_run(struct cache_set *c)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
struct uuid_entry *u;
|
|
|
|
|
|
|
|
for (u = c->uuids;
|
2018-02-28 01:49:29 +08:00
|
|
|
u < c->uuids + c->nr_uuids && !ret;
|
2013-03-24 07:11:31 +08:00
|
|
|
u++)
|
|
|
|
if (UUID_FLASH_ONLY(u))
|
|
|
|
ret = flash_dev_run(c, u);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bch_flash_dev_create(struct cache_set *c, uint64_t size)
|
|
|
|
{
|
|
|
|
struct uuid_entry *u;
|
|
|
|
|
|
|
|
if (test_bit(CACHE_SET_STOPPING, &c->flags))
|
|
|
|
return -EINTR;
|
|
|
|
|
2014-07-12 03:17:41 +08:00
|
|
|
if (!test_bit(CACHE_SET_RUNNING, &c->flags))
|
|
|
|
return -EPERM;
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
u = uuid_find_empty(c);
|
|
|
|
if (!u) {
|
|
|
|
pr_err("Can't create volume, no room for UUID");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
get_random_bytes(u->uuid, 16);
|
|
|
|
memset(u->label, 0, 32);
|
2018-07-26 12:17:41 +08:00
|
|
|
u->first_reg = u->last_reg = cpu_to_le32((u32)ktime_get_real_seconds());
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
SET_UUID_FLASH_ONLY(u, 1);
|
|
|
|
u->sectors = size >> 9;
|
|
|
|
|
|
|
|
bch_uuid_write(c);
|
|
|
|
|
|
|
|
return flash_dev_run(c, u);
|
|
|
|
}
|
|
|
|
|
bcache: add io_disable to struct cached_dev
If a bcache device is configured to writeback mode, current code does not
handle write I/O errors on backing devices properly.
In writeback mode, write request is written to cache device, and
latter being flushed to backing device. If I/O failed when writing from
cache device to the backing device, bcache code just ignores the error and
upper layer code is NOT noticed that the backing device is broken.
This patch tries to handle backing device failure like how the cache device
failure is handled,
- Add a error counter 'io_errors' and error limit 'error_limit' in struct
cached_dev. Add another io_disable to struct cached_dev to disable I/Os
on the problematic backing device.
- When I/O error happens on backing device, increase io_errors counter. And
if io_errors reaches error_limit, set cache_dev->io_disable to true, and
stop the bcache device.
The result is, if backing device is broken of disconnected, and I/O errors
reach its error limit, backing device will be disabled and the associated
bcache device will be removed from system.
Changelog:
v2: remove "bcache: " prefix in pr_error(), and use correct name string to
print out bcache device gendisk name.
v1: indeed this is new added in v2 patch set.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:25 +08:00
|
|
|
bool bch_cached_dev_error(struct cached_dev *dc)
|
|
|
|
{
|
|
|
|
if (!dc || test_bit(BCACHE_DEV_CLOSING, &dc->disk.flags))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
dc->io_disable = true;
|
|
|
|
/* make others know io_disable is true earlier */
|
|
|
|
smp_mb();
|
|
|
|
|
|
|
|
pr_err("stop %s: too many IO errors on backing device %s\n",
|
2018-05-03 18:51:32 +08:00
|
|
|
dc->disk.disk->disk_name, dc->backing_dev_name);
|
bcache: add io_disable to struct cached_dev
If a bcache device is configured to writeback mode, current code does not
handle write I/O errors on backing devices properly.
In writeback mode, write request is written to cache device, and
latter being flushed to backing device. If I/O failed when writing from
cache device to the backing device, bcache code just ignores the error and
upper layer code is NOT noticed that the backing device is broken.
This patch tries to handle backing device failure like how the cache device
failure is handled,
- Add a error counter 'io_errors' and error limit 'error_limit' in struct
cached_dev. Add another io_disable to struct cached_dev to disable I/Os
on the problematic backing device.
- When I/O error happens on backing device, increase io_errors counter. And
if io_errors reaches error_limit, set cache_dev->io_disable to true, and
stop the bcache device.
The result is, if backing device is broken of disconnected, and I/O errors
reach its error limit, backing device will be disabled and the associated
bcache device will be removed from system.
Changelog:
v2: remove "bcache: " prefix in pr_error(), and use correct name string to
print out bcache device gendisk name.
v1: indeed this is new added in v2 patch set.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:25 +08:00
|
|
|
|
|
|
|
bcache_device_stop(&dc->disk);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
/* Cache set */
|
|
|
|
|
|
|
|
__printf(2, 3)
|
|
|
|
bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
|
2013-07-12 10:42:51 +08:00
|
|
|
if (c->on_error != ON_ERROR_PANIC &&
|
|
|
|
test_bit(CACHE_SET_STOPPING, &c->flags))
|
2013-03-24 07:11:31 +08:00
|
|
|
return false;
|
|
|
|
|
bcache: add CACHE_SET_IO_DISABLE to struct cache_set flags
When too many I/Os failed on cache device, bch_cache_set_error() is called
in the error handling code path to retire whole problematic cache set. If
new I/O requests continue to come and take refcount dc->count, the cache
set won't be retired immediately, this is a problem.
Further more, there are several kernel thread and self-armed kernel work
may still running after bch_cache_set_error() is called. It needs to wait
quite a while for them to stop, or they won't stop at all. They also
prevent the cache set from being retired.
The solution in this patch is, to add per cache set flag to disable I/O
request on this cache and all attached backing devices. Then new coming I/O
requests can be rejected in *_make_request() before taking refcount, kernel
threads and self-armed kernel worker can stop very fast when flags bit
CACHE_SET_IO_DISABLE is set.
Because bcache also do internal I/Os for writeback, garbage collection,
bucket allocation, journaling, this kind of I/O should be disabled after
bch_cache_set_error() is called. So closure_bio_submit() is modified to
check whether CACHE_SET_IO_DISABLE is set on cache_set->flags. If set,
closure_bio_submit() will set bio->bi_status to BLK_STS_IOERR and
return, generic_make_request() won't be called.
A sysfs interface is also added to set or clear CACHE_SET_IO_DISABLE bit
from cache_set->flags, to disable or enable cache set I/O for debugging. It
is helpful to trigger more corner case issues for failed cache device.
Changelog
v4, add wait_for_kthread_stop(), and call it before exits writeback and gc
kernel threads.
v3, change CACHE_SET_IO_DISABLE from 4 to 3, since it is bit index.
remove "bcache: " prefix when printing out kernel message.
v2, more changes by previous review,
- Use CACHE_SET_IO_DISABLE of cache_set->flags, suggested by Junhui.
- Check CACHE_SET_IO_DISABLE in bch_btree_gc() to stop a while-loop, this
is reported and inspired from origal patch of Pavel Vazharov.
v1, initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Pavel Vazharov <freakpv@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:17 +08:00
|
|
|
if (test_and_set_bit(CACHE_SET_IO_DISABLE, &c->flags))
|
2018-05-03 18:51:37 +08:00
|
|
|
pr_info("CACHE_SET_IO_DISABLE already set");
|
bcache: add CACHE_SET_IO_DISABLE to struct cache_set flags
When too many I/Os failed on cache device, bch_cache_set_error() is called
in the error handling code path to retire whole problematic cache set. If
new I/O requests continue to come and take refcount dc->count, the cache
set won't be retired immediately, this is a problem.
Further more, there are several kernel thread and self-armed kernel work
may still running after bch_cache_set_error() is called. It needs to wait
quite a while for them to stop, or they won't stop at all. They also
prevent the cache set from being retired.
The solution in this patch is, to add per cache set flag to disable I/O
request on this cache and all attached backing devices. Then new coming I/O
requests can be rejected in *_make_request() before taking refcount, kernel
threads and self-armed kernel worker can stop very fast when flags bit
CACHE_SET_IO_DISABLE is set.
Because bcache also do internal I/Os for writeback, garbage collection,
bucket allocation, journaling, this kind of I/O should be disabled after
bch_cache_set_error() is called. So closure_bio_submit() is modified to
check whether CACHE_SET_IO_DISABLE is set on cache_set->flags. If set,
closure_bio_submit() will set bio->bi_status to BLK_STS_IOERR and
return, generic_make_request() won't be called.
A sysfs interface is also added to set or clear CACHE_SET_IO_DISABLE bit
from cache_set->flags, to disable or enable cache set I/O for debugging. It
is helpful to trigger more corner case issues for failed cache device.
Changelog
v4, add wait_for_kthread_stop(), and call it before exits writeback and gc
kernel threads.
v3, change CACHE_SET_IO_DISABLE from 4 to 3, since it is bit index.
remove "bcache: " prefix when printing out kernel message.
v2, more changes by previous review,
- Use CACHE_SET_IO_DISABLE of cache_set->flags, suggested by Junhui.
- Check CACHE_SET_IO_DISABLE in bch_btree_gc() to stop a while-loop, this
is reported and inspired from origal patch of Pavel Vazharov.
v1, initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Pavel Vazharov <freakpv@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:17 +08:00
|
|
|
|
2018-08-11 13:19:55 +08:00
|
|
|
/*
|
|
|
|
* XXX: we can be called from atomic context
|
|
|
|
* acquire_console_sem();
|
|
|
|
*/
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-08-11 13:19:49 +08:00
|
|
|
pr_err("bcache: error on %pU: ", c->sb.set_uuid);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
vprintk(fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
2018-08-11 13:19:49 +08:00
|
|
|
pr_err(", disabling caching\n");
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-07-12 10:42:51 +08:00
|
|
|
if (c->on_error == ON_ERROR_PANIC)
|
|
|
|
panic("panic forced after error\n");
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_cache_set_unregister(c);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-04-25 00:48:35 +08:00
|
|
|
/* When c->kobj released */
|
2013-03-24 07:11:31 +08:00
|
|
|
void bch_cache_set_release(struct kobject *kobj)
|
|
|
|
{
|
|
|
|
struct cache_set *c = container_of(kobj, struct cache_set, kobj);
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
kfree(c);
|
|
|
|
module_put(THIS_MODULE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cache_set_free(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cache_set *c = container_of(cl, struct cache_set, cl);
|
|
|
|
struct cache *ca;
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-12-13 22:53:47 +08:00
|
|
|
debugfs_remove(c->debug);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
bch_open_buckets_free(c);
|
|
|
|
bch_btree_cache_free(c);
|
|
|
|
bch_journal_free(c);
|
|
|
|
|
2019-04-25 00:48:31 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
for_each_cache(ca, c, i)
|
2014-06-20 06:05:59 +08:00
|
|
|
if (ca) {
|
|
|
|
ca->set = NULL;
|
|
|
|
c->cache[ca->sb.nr_this_dev] = NULL;
|
2013-03-24 07:11:31 +08:00
|
|
|
kobject_put(&ca->kobj);
|
2014-06-20 06:05:59 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-09-11 13:53:34 +08:00
|
|
|
bch_bset_sort_state_free(&c->sort);
|
2013-03-24 07:11:31 +08:00
|
|
|
free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c)));
|
|
|
|
|
2014-01-10 08:03:04 +08:00
|
|
|
if (c->moving_gc_wq)
|
|
|
|
destroy_workqueue(c->moving_gc_wq);
|
2018-05-21 06:25:51 +08:00
|
|
|
bioset_exit(&c->bio_split);
|
|
|
|
mempool_exit(&c->fill_iter);
|
|
|
|
mempool_exit(&c->bio_meta);
|
|
|
|
mempool_exit(&c->search);
|
2013-03-24 07:11:31 +08:00
|
|
|
kfree(c->devices);
|
|
|
|
|
|
|
|
list_del(&c->list);
|
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
|
|
|
|
pr_info("Cache set %pU unregistered", c->sb.set_uuid);
|
|
|
|
wake_up(&unregister_wait);
|
|
|
|
|
|
|
|
closure_debug_destroy(&c->cl);
|
|
|
|
kobject_put(&c->kobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cache_set_flush(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cache_set *c = container_of(cl, struct cache_set, caching);
|
2013-07-11 09:31:58 +08:00
|
|
|
struct cache *ca;
|
2013-03-24 07:11:31 +08:00
|
|
|
struct btree *b;
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
bch_cache_accounting_destroy(&c->accounting);
|
|
|
|
|
|
|
|
kobject_put(&c->internal);
|
|
|
|
kobject_del(&c->kobj);
|
|
|
|
|
bcache: check c->gc_thread by IS_ERR_OR_NULL in cache_set_flush()
When system memory is in heavy pressure, bch_gc_thread_start() from
run_cache_set() may fail due to out of memory. In such condition,
c->gc_thread is assigned to -ENOMEM, not NULL pointer. Then in following
failure code path bch_cache_set_error(), when cache_set_flush() gets
called, the code piece to stop c->gc_thread is broken,
if (!IS_ERR_OR_NULL(c->gc_thread))
kthread_stop(c->gc_thread);
And KASAN catches such NULL pointer deference problem, with the warning
information:
[ 561.207881] ==================================================================
[ 561.207900] BUG: KASAN: null-ptr-deref in kthread_stop+0x3b/0x440
[ 561.207904] Write of size 4 at addr 000000000000001c by task kworker/15:1/313
[ 561.207913] CPU: 15 PID: 313 Comm: kworker/15:1 Tainted: G W 5.0.0-vanilla+ #3
[ 561.207916] Hardware name: Lenovo ThinkSystem SR650 -[7X05CTO1WW]-/-[7X05CTO1WW]-, BIOS -[IVE136T-2.10]- 03/22/2019
[ 561.207935] Workqueue: events cache_set_flush [bcache]
[ 561.207940] Call Trace:
[ 561.207948] dump_stack+0x9a/0xeb
[ 561.207955] ? kthread_stop+0x3b/0x440
[ 561.207960] ? kthread_stop+0x3b/0x440
[ 561.207965] kasan_report+0x176/0x192
[ 561.207973] ? kthread_stop+0x3b/0x440
[ 561.207981] kthread_stop+0x3b/0x440
[ 561.207995] cache_set_flush+0xd4/0x6d0 [bcache]
[ 561.208008] process_one_work+0x856/0x1620
[ 561.208015] ? find_held_lock+0x39/0x1d0
[ 561.208028] ? drain_workqueue+0x380/0x380
[ 561.208048] worker_thread+0x87/0xb80
[ 561.208058] ? __kthread_parkme+0xb6/0x180
[ 561.208067] ? process_one_work+0x1620/0x1620
[ 561.208072] kthread+0x326/0x3e0
[ 561.208079] ? kthread_create_worker_on_cpu+0xc0/0xc0
[ 561.208090] ret_from_fork+0x3a/0x50
[ 561.208110] ==================================================================
[ 561.208113] Disabling lock debugging due to kernel taint
[ 561.208115] irq event stamp: 11800231
[ 561.208126] hardirqs last enabled at (11800231): [<ffffffff83008538>] do_syscall_64+0x18/0x410
[ 561.208127] BUG: unable to handle kernel NULL pointer dereference at 000000000000001c
[ 561.208129] #PF error: [WRITE]
[ 561.312253] hardirqs last disabled at (11800230): [<ffffffff830052ff>] trace_hardirqs_off_thunk+0x1a/0x1c
[ 561.312259] softirqs last enabled at (11799832): [<ffffffff850005c7>] __do_softirq+0x5c7/0x8c3
[ 561.405975] PGD 0 P4D 0
[ 561.442494] softirqs last disabled at (11799821): [<ffffffff831add2c>] irq_exit+0x1ac/0x1e0
[ 561.791359] Oops: 0002 [#1] SMP KASAN NOPTI
[ 561.791362] CPU: 15 PID: 313 Comm: kworker/15:1 Tainted: G B W 5.0.0-vanilla+ #3
[ 561.791363] Hardware name: Lenovo ThinkSystem SR650 -[7X05CTO1WW]-/-[7X05CTO1WW]-, BIOS -[IVE136T-2.10]- 03/22/2019
[ 561.791371] Workqueue: events cache_set_flush [bcache]
[ 561.791374] RIP: 0010:kthread_stop+0x3b/0x440
[ 561.791376] Code: 00 00 65 8b 05 26 d5 e0 7c 89 c0 48 0f a3 05 ec aa df 02 0f 82 dc 02 00 00 4c 8d 63 20 be 04 00 00 00 4c 89 e7 e8 65 c5 53 00 <f0> ff 43 20 48 8d 7b 24 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48
[ 561.791377] RSP: 0018:ffff88872fc8fd10 EFLAGS: 00010286
[ 561.838895] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 561.838916] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 561.838934] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 561.838948] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 561.838966] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 561.838979] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 561.838996] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 563.067028] RAX: 0000000000000000 RBX: fffffffffffffffc RCX: ffffffff832dd314
[ 563.067030] RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000000297
[ 563.067032] RBP: ffff88872fc8fe88 R08: fffffbfff0b8213d R09: fffffbfff0b8213d
[ 563.067034] R10: 0000000000000001 R11: fffffbfff0b8213c R12: 000000000000001c
[ 563.408618] R13: ffff88dc61cc0f68 R14: ffff888102b94900 R15: ffff88dc61cc0f68
[ 563.408620] FS: 0000000000000000(0000) GS:ffff888f7dc00000(0000) knlGS:0000000000000000
[ 563.408622] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 563.408623] CR2: 000000000000001c CR3: 0000000f48a1a004 CR4: 00000000007606e0
[ 563.408625] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 563.408627] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 563.904795] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 563.915796] PKRU: 55555554
[ 563.915797] Call Trace:
[ 563.915807] cache_set_flush+0xd4/0x6d0 [bcache]
[ 563.915812] process_one_work+0x856/0x1620
[ 564.001226] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 564.033563] ? find_held_lock+0x39/0x1d0
[ 564.033567] ? drain_workqueue+0x380/0x380
[ 564.033574] worker_thread+0x87/0xb80
[ 564.062823] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 564.118042] ? __kthread_parkme+0xb6/0x180
[ 564.118046] ? process_one_work+0x1620/0x1620
[ 564.118048] kthread+0x326/0x3e0
[ 564.118050] ? kthread_create_worker_on_cpu+0xc0/0xc0
[ 564.167066] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 564.252441] ret_from_fork+0x3a/0x50
[ 564.252447] Modules linked in: msr rpcrdma sunrpc rdma_ucm ib_iser ib_umad rdma_cm ib_ipoib i40iw configfs iw_cm ib_cm libiscsi scsi_transport_iscsi mlx4_ib ib_uverbs mlx4_en ib_core nls_iso8859_1 nls_cp437 vfat fat intel_rapl skx_edac x86_pkg_temp_thermal coretemp iTCO_wdt iTCO_vendor_support crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel ses raid0 aesni_intel cdc_ether enclosure usbnet ipmi_ssif joydev aes_x86_64 i40e scsi_transport_sas mii bcache md_mod crypto_simd mei_me ioatdma crc64 ptp cryptd pcspkr i2c_i801 mlx4_core glue_helper pps_core mei lpc_ich dca wmi ipmi_si ipmi_devintf nd_pmem dax_pmem nd_btt ipmi_msghandler device_dax pcc_cpufreq button hid_generic usbhid mgag200 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect xhci_pci sysimgblt fb_sys_fops xhci_hcd ttm megaraid_sas drm usbcore nfit libnvdimm sg dm_multipath dm_mod scsi_dh_rdac scsi_dh_emc scsi_dh_alua efivarfs
[ 564.299390] bcache: bch_count_io_errors() nvme0n1: IO error on writing btree.
[ 564.348360] CR2: 000000000000001c
[ 564.348362] ---[ end trace b7f0e5cc7b2103b0 ]---
Therefore, it is not enough to only check whether c->gc_thread is NULL,
we should use IS_ERR_OR_NULL() to check both NULL pointer and error
value.
This patch changes the above buggy code piece in this way,
if (!IS_ERR_OR_NULL(c->gc_thread))
kthread_stop(c->gc_thread);
Signed-off-by: Coly Li <colyli@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2019-06-28 19:59:25 +08:00
|
|
|
if (!IS_ERR_OR_NULL(c->gc_thread))
|
2013-10-25 08:19:26 +08:00
|
|
|
kthread_stop(c->gc_thread);
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
if (!IS_ERR_OR_NULL(c->root))
|
|
|
|
list_add(&c->root->list, &c->btree_cache);
|
|
|
|
|
2019-06-28 19:59:28 +08:00
|
|
|
/*
|
|
|
|
* Avoid flushing cached nodes if cache set is retiring
|
|
|
|
* due to too many I/O errors detected.
|
|
|
|
*/
|
|
|
|
if (!test_bit(CACHE_SET_IO_DISABLE, &c->flags))
|
|
|
|
list_for_each_entry(b, &c->btree_cache, list) {
|
|
|
|
mutex_lock(&b->write_lock);
|
|
|
|
if (btree_node_dirty(b))
|
|
|
|
__bch_btree_node_write(b, NULL);
|
|
|
|
mutex_unlock(&b->write_lock);
|
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-07-11 09:31:58 +08:00
|
|
|
for_each_cache(ca, c, i)
|
|
|
|
if (ca->alloc_thread)
|
|
|
|
kthread_stop(ca->alloc_thread);
|
|
|
|
|
2014-03-20 08:49:37 +08:00
|
|
|
if (c->journal.cur) {
|
|
|
|
cancel_delayed_work_sync(&c->journal.work);
|
|
|
|
/* flush last journal entry if needed */
|
|
|
|
c->journal.work.work.func(&c->journal.work.work);
|
|
|
|
}
|
2014-02-20 11:48:26 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_return(cl);
|
|
|
|
}
|
|
|
|
|
bcache: add stop_when_cache_set_failed option to backing device
When there are too many I/O errors on cache device, current bcache code
will retire the whole cache set, and detach all bcache devices. But the
detached bcache devices are not stopped, which is problematic when bcache
is in writeback mode.
If the retired cache set has dirty data of backing devices, continue
writing to bcache device will write to backing device directly. If the
LBA of write request has a dirty version cached on cache device, next time
when the cache device is re-registered and backing device re-attached to
it again, the stale dirty data on cache device will be written to backing
device, and overwrite latest directly written data. This situation causes
a quite data corruption.
But we cannot simply stop all attached bcache devices when the cache set is
broken or disconnected. For example, use bcache to accelerate performance
of an email service. In such workload, if cache device is broken but no
dirty data lost, keep the bcache device alive and permit email service
continue to access user data might be a better solution for the cache
device failure.
Nix <nix@esperi.org.uk> points out the issue and provides the above example
to explain why it might be necessary to not stop bcache device for broken
cache device. Pavel Goran <via-bcache@pvgoran.name> provides a brilliant
suggestion to provide "always" and "auto" options to per-cached device
sysfs file stop_when_cache_set_failed. If cache set is retiring and the
backing device has no dirty data on cache, it should be safe to keep the
bcache device alive. In this case, if stop_when_cache_set_failed is set to
"auto", the device failure handling code will not stop this bcache device
and permit application to access the backing device with a unattached
bcache device.
Changelog:
[mlyle: edited to not break string constants across lines]
v3: fix typos pointed out by Nix.
v2: change option values of stop_when_cache_set_failed from 1/0 to
"auto"/"always".
v1: initial version, stop_when_cache_set_failed can be 0 (not stop) or 1
(always stop).
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Cc: Nix <nix@esperi.org.uk>
Cc: Pavel Goran <via-bcache@pvgoran.name>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:18 +08:00
|
|
|
/*
|
|
|
|
* This function is only called when CACHE_SET_IO_DISABLE is set, which means
|
|
|
|
* cache set is unregistering due to too many I/O errors. In this condition,
|
|
|
|
* the bcache device might be stopped, it depends on stop_when_cache_set_failed
|
|
|
|
* value and whether the broken cache has dirty data:
|
|
|
|
*
|
|
|
|
* dc->stop_when_cache_set_failed dc->has_dirty stop bcache device
|
|
|
|
* BCH_CACHED_STOP_AUTO 0 NO
|
|
|
|
* BCH_CACHED_STOP_AUTO 1 YES
|
|
|
|
* BCH_CACHED_DEV_STOP_ALWAYS 0 YES
|
|
|
|
* BCH_CACHED_DEV_STOP_ALWAYS 1 YES
|
|
|
|
*
|
|
|
|
* The expected behavior is, if stop_when_cache_set_failed is configured to
|
|
|
|
* "auto" via sysfs interface, the bcache device will not be stopped if the
|
|
|
|
* backing device is clean on the broken cache device.
|
|
|
|
*/
|
|
|
|
static void conditional_stop_bcache_device(struct cache_set *c,
|
|
|
|
struct bcache_device *d,
|
|
|
|
struct cached_dev *dc)
|
|
|
|
{
|
|
|
|
if (dc->stop_when_cache_set_failed == BCH_CACHED_DEV_STOP_ALWAYS) {
|
|
|
|
pr_warn("stop_when_cache_set_failed of %s is \"always\", stop it for failed cache set %pU.",
|
|
|
|
d->disk->disk_name, c->sb.set_uuid);
|
|
|
|
bcache_device_stop(d);
|
|
|
|
} else if (atomic_read(&dc->has_dirty)) {
|
|
|
|
/*
|
|
|
|
* dc->stop_when_cache_set_failed == BCH_CACHED_STOP_AUTO
|
|
|
|
* and dc->has_dirty == 1
|
|
|
|
*/
|
|
|
|
pr_warn("stop_when_cache_set_failed of %s is \"auto\" and cache is dirty, stop it to avoid potential data corruption.",
|
|
|
|
d->disk->disk_name);
|
2019-02-09 12:52:57 +08:00
|
|
|
/*
|
|
|
|
* There might be a small time gap that cache set is
|
|
|
|
* released but bcache device is not. Inside this time
|
|
|
|
* gap, regular I/O requests will directly go into
|
|
|
|
* backing device as no cache set attached to. This
|
|
|
|
* behavior may also introduce potential inconsistence
|
|
|
|
* data in writeback mode while cache is dirty.
|
|
|
|
* Therefore before calling bcache_device_stop() due
|
|
|
|
* to a broken cache device, dc->io_disable should be
|
|
|
|
* explicitly set to true.
|
|
|
|
*/
|
|
|
|
dc->io_disable = true;
|
|
|
|
/* make others know io_disable is true earlier */
|
|
|
|
smp_mb();
|
|
|
|
bcache_device_stop(d);
|
bcache: add stop_when_cache_set_failed option to backing device
When there are too many I/O errors on cache device, current bcache code
will retire the whole cache set, and detach all bcache devices. But the
detached bcache devices are not stopped, which is problematic when bcache
is in writeback mode.
If the retired cache set has dirty data of backing devices, continue
writing to bcache device will write to backing device directly. If the
LBA of write request has a dirty version cached on cache device, next time
when the cache device is re-registered and backing device re-attached to
it again, the stale dirty data on cache device will be written to backing
device, and overwrite latest directly written data. This situation causes
a quite data corruption.
But we cannot simply stop all attached bcache devices when the cache set is
broken or disconnected. For example, use bcache to accelerate performance
of an email service. In such workload, if cache device is broken but no
dirty data lost, keep the bcache device alive and permit email service
continue to access user data might be a better solution for the cache
device failure.
Nix <nix@esperi.org.uk> points out the issue and provides the above example
to explain why it might be necessary to not stop bcache device for broken
cache device. Pavel Goran <via-bcache@pvgoran.name> provides a brilliant
suggestion to provide "always" and "auto" options to per-cached device
sysfs file stop_when_cache_set_failed. If cache set is retiring and the
backing device has no dirty data on cache, it should be safe to keep the
bcache device alive. In this case, if stop_when_cache_set_failed is set to
"auto", the device failure handling code will not stop this bcache device
and permit application to access the backing device with a unattached
bcache device.
Changelog:
[mlyle: edited to not break string constants across lines]
v3: fix typos pointed out by Nix.
v2: change option values of stop_when_cache_set_failed from 1/0 to
"auto"/"always".
v1: initial version, stop_when_cache_set_failed can be 0 (not stop) or 1
(always stop).
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Cc: Nix <nix@esperi.org.uk>
Cc: Pavel Goran <via-bcache@pvgoran.name>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:18 +08:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* dc->stop_when_cache_set_failed == BCH_CACHED_STOP_AUTO
|
|
|
|
* and dc->has_dirty == 0
|
|
|
|
*/
|
|
|
|
pr_warn("stop_when_cache_set_failed of %s is \"auto\" and cache is clean, keep it alive.",
|
|
|
|
d->disk->disk_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
static void __cache_set_unregister(struct closure *cl)
|
|
|
|
{
|
|
|
|
struct cache_set *c = container_of(cl, struct cache_set, caching);
|
2013-07-11 12:03:25 +08:00
|
|
|
struct cached_dev *dc;
|
bcache: add stop_when_cache_set_failed option to backing device
When there are too many I/O errors on cache device, current bcache code
will retire the whole cache set, and detach all bcache devices. But the
detached bcache devices are not stopped, which is problematic when bcache
is in writeback mode.
If the retired cache set has dirty data of backing devices, continue
writing to bcache device will write to backing device directly. If the
LBA of write request has a dirty version cached on cache device, next time
when the cache device is re-registered and backing device re-attached to
it again, the stale dirty data on cache device will be written to backing
device, and overwrite latest directly written data. This situation causes
a quite data corruption.
But we cannot simply stop all attached bcache devices when the cache set is
broken or disconnected. For example, use bcache to accelerate performance
of an email service. In such workload, if cache device is broken but no
dirty data lost, keep the bcache device alive and permit email service
continue to access user data might be a better solution for the cache
device failure.
Nix <nix@esperi.org.uk> points out the issue and provides the above example
to explain why it might be necessary to not stop bcache device for broken
cache device. Pavel Goran <via-bcache@pvgoran.name> provides a brilliant
suggestion to provide "always" and "auto" options to per-cached device
sysfs file stop_when_cache_set_failed. If cache set is retiring and the
backing device has no dirty data on cache, it should be safe to keep the
bcache device alive. In this case, if stop_when_cache_set_failed is set to
"auto", the device failure handling code will not stop this bcache device
and permit application to access the backing device with a unattached
bcache device.
Changelog:
[mlyle: edited to not break string constants across lines]
v3: fix typos pointed out by Nix.
v2: change option values of stop_when_cache_set_failed from 1/0 to
"auto"/"always".
v1: initial version, stop_when_cache_set_failed can be 0 (not stop) or 1
(always stop).
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Cc: Nix <nix@esperi.org.uk>
Cc: Pavel Goran <via-bcache@pvgoran.name>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:18 +08:00
|
|
|
struct bcache_device *d;
|
2013-03-24 07:11:31 +08:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
mutex_lock(&bch_register_lock);
|
|
|
|
|
bcache: add stop_when_cache_set_failed option to backing device
When there are too many I/O errors on cache device, current bcache code
will retire the whole cache set, and detach all bcache devices. But the
detached bcache devices are not stopped, which is problematic when bcache
is in writeback mode.
If the retired cache set has dirty data of backing devices, continue
writing to bcache device will write to backing device directly. If the
LBA of write request has a dirty version cached on cache device, next time
when the cache device is re-registered and backing device re-attached to
it again, the stale dirty data on cache device will be written to backing
device, and overwrite latest directly written data. This situation causes
a quite data corruption.
But we cannot simply stop all attached bcache devices when the cache set is
broken or disconnected. For example, use bcache to accelerate performance
of an email service. In such workload, if cache device is broken but no
dirty data lost, keep the bcache device alive and permit email service
continue to access user data might be a better solution for the cache
device failure.
Nix <nix@esperi.org.uk> points out the issue and provides the above example
to explain why it might be necessary to not stop bcache device for broken
cache device. Pavel Goran <via-bcache@pvgoran.name> provides a brilliant
suggestion to provide "always" and "auto" options to per-cached device
sysfs file stop_when_cache_set_failed. If cache set is retiring and the
backing device has no dirty data on cache, it should be safe to keep the
bcache device alive. In this case, if stop_when_cache_set_failed is set to
"auto", the device failure handling code will not stop this bcache device
and permit application to access the backing device with a unattached
bcache device.
Changelog:
[mlyle: edited to not break string constants across lines]
v3: fix typos pointed out by Nix.
v2: change option values of stop_when_cache_set_failed from 1/0 to
"auto"/"always".
v1: initial version, stop_when_cache_set_failed can be 0 (not stop) or 1
(always stop).
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Cc: Nix <nix@esperi.org.uk>
Cc: Pavel Goran <via-bcache@pvgoran.name>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:18 +08:00
|
|
|
for (i = 0; i < c->devices_max_used; i++) {
|
|
|
|
d = c->devices[i];
|
|
|
|
if (!d)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!UUID_FLASH_ONLY(&c->uuids[i]) &&
|
|
|
|
test_bit(CACHE_SET_UNREGISTERING, &c->flags)) {
|
|
|
|
dc = container_of(d, struct cached_dev, disk);
|
|
|
|
bch_cached_dev_detach(dc);
|
|
|
|
if (test_bit(CACHE_SET_IO_DISABLE, &c->flags))
|
|
|
|
conditional_stop_bcache_device(c, d, dc);
|
|
|
|
} else {
|
|
|
|
bcache_device_stop(d);
|
2013-07-11 12:03:25 +08:00
|
|
|
}
|
bcache: add stop_when_cache_set_failed option to backing device
When there are too many I/O errors on cache device, current bcache code
will retire the whole cache set, and detach all bcache devices. But the
detached bcache devices are not stopped, which is problematic when bcache
is in writeback mode.
If the retired cache set has dirty data of backing devices, continue
writing to bcache device will write to backing device directly. If the
LBA of write request has a dirty version cached on cache device, next time
when the cache device is re-registered and backing device re-attached to
it again, the stale dirty data on cache device will be written to backing
device, and overwrite latest directly written data. This situation causes
a quite data corruption.
But we cannot simply stop all attached bcache devices when the cache set is
broken or disconnected. For example, use bcache to accelerate performance
of an email service. In such workload, if cache device is broken but no
dirty data lost, keep the bcache device alive and permit email service
continue to access user data might be a better solution for the cache
device failure.
Nix <nix@esperi.org.uk> points out the issue and provides the above example
to explain why it might be necessary to not stop bcache device for broken
cache device. Pavel Goran <via-bcache@pvgoran.name> provides a brilliant
suggestion to provide "always" and "auto" options to per-cached device
sysfs file stop_when_cache_set_failed. If cache set is retiring and the
backing device has no dirty data on cache, it should be safe to keep the
bcache device alive. In this case, if stop_when_cache_set_failed is set to
"auto", the device failure handling code will not stop this bcache device
and permit application to access the backing device with a unattached
bcache device.
Changelog:
[mlyle: edited to not break string constants across lines]
v3: fix typos pointed out by Nix.
v2: change option values of stop_when_cache_set_failed from 1/0 to
"auto"/"always".
v1: initial version, stop_when_cache_set_failed can be 0 (not stop) or 1
(always stop).
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Michael Lyle <mlyle@lyle.org>
Cc: Nix <nix@esperi.org.uk>
Cc: Pavel Goran <via-bcache@pvgoran.name>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:18 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
|
|
|
|
continue_at(cl, cache_set_flush, system_wq);
|
|
|
|
}
|
|
|
|
|
|
|
|
void bch_cache_set_stop(struct cache_set *c)
|
|
|
|
{
|
|
|
|
if (!test_and_set_bit(CACHE_SET_STOPPING, &c->flags))
|
2019-04-25 00:48:39 +08:00
|
|
|
/* closure_fn set to __cache_set_unregister() */
|
2013-03-24 07:11:31 +08:00
|
|
|
closure_queue(&c->caching);
|
|
|
|
}
|
|
|
|
|
|
|
|
void bch_cache_set_unregister(struct cache_set *c)
|
|
|
|
{
|
|
|
|
set_bit(CACHE_SET_UNREGISTERING, &c->flags);
|
|
|
|
bch_cache_set_stop(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define alloc_bucket_pages(gfp, c) \
|
|
|
|
((void *) __get_free_pages(__GFP_ZERO|gfp, ilog2(bucket_pages(c))))
|
|
|
|
|
|
|
|
struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
|
|
|
|
{
|
|
|
|
int iter_size;
|
|
|
|
struct cache_set *c = kzalloc(sizeof(struct cache_set), GFP_KERNEL);
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
if (!c)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
__module_get(THIS_MODULE);
|
|
|
|
closure_init(&c->cl, NULL);
|
|
|
|
set_closure_fn(&c->cl, cache_set_free, system_wq);
|
|
|
|
|
|
|
|
closure_init(&c->caching, &c->cl);
|
|
|
|
set_closure_fn(&c->caching, __cache_set_unregister, system_wq);
|
|
|
|
|
|
|
|
/* Maybe create continue_at_noreturn() and use it here? */
|
|
|
|
closure_set_stopped(&c->cl);
|
|
|
|
closure_put(&c->cl);
|
|
|
|
|
|
|
|
kobject_init(&c->kobj, &bch_cache_set_ktype);
|
|
|
|
kobject_init(&c->internal, &bch_cache_set_internal_ktype);
|
|
|
|
|
|
|
|
bch_cache_accounting_init(&c->accounting, &c->cl);
|
|
|
|
|
|
|
|
memcpy(c->sb.set_uuid, sb->set_uuid, 16);
|
|
|
|
c->sb.block_size = sb->block_size;
|
|
|
|
c->sb.bucket_size = sb->bucket_size;
|
|
|
|
c->sb.nr_in_set = sb->nr_in_set;
|
|
|
|
c->sb.last_mount = sb->last_mount;
|
|
|
|
c->bucket_bits = ilog2(sb->bucket_size);
|
|
|
|
c->block_bits = ilog2(sb->block_size);
|
|
|
|
c->nr_uuids = bucket_bytes(c) / sizeof(struct uuid_entry);
|
2018-01-09 04:21:28 +08:00
|
|
|
c->devices_max_used = 0;
|
2018-08-09 15:48:49 +08:00
|
|
|
atomic_set(&c->attached_dev_nr, 0);
|
2013-12-18 15:49:49 +08:00
|
|
|
c->btree_pages = bucket_pages(c);
|
2013-03-24 07:11:31 +08:00
|
|
|
if (c->btree_pages > BTREE_MAX_PAGES)
|
|
|
|
c->btree_pages = max_t(int, c->btree_pages / 4,
|
|
|
|
BTREE_MAX_PAGES);
|
|
|
|
|
2013-12-17 07:27:25 +08:00
|
|
|
sema_init(&c->sb_write_mutex, 1);
|
2013-07-25 08:27:07 +08:00
|
|
|
mutex_init(&c->bucket_lock);
|
2014-03-18 08:15:53 +08:00
|
|
|
init_waitqueue_head(&c->btree_cache_wait);
|
2013-07-25 08:29:09 +08:00
|
|
|
init_waitqueue_head(&c->bucket_wait);
|
2016-10-27 11:31:17 +08:00
|
|
|
init_waitqueue_head(&c->gc_wait);
|
2013-12-17 07:27:25 +08:00
|
|
|
sema_init(&c->uuid_write_mutex, 1);
|
2013-07-31 15:03:54 +08:00
|
|
|
|
|
|
|
spin_lock_init(&c->btree_gc_time.lock);
|
|
|
|
spin_lock_init(&c->btree_split_time.lock);
|
|
|
|
spin_lock_init(&c->btree_read_time.lock);
|
2013-07-25 08:27:07 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_moving_init_cache_set(c);
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&c->list);
|
|
|
|
INIT_LIST_HEAD(&c->cached_devs);
|
|
|
|
INIT_LIST_HEAD(&c->btree_cache);
|
|
|
|
INIT_LIST_HEAD(&c->btree_cache_freeable);
|
|
|
|
INIT_LIST_HEAD(&c->btree_cache_freed);
|
|
|
|
INIT_LIST_HEAD(&c->data_buckets);
|
|
|
|
|
|
|
|
iter_size = (sb->bucket_size / sb->block_size + 1) *
|
|
|
|
sizeof(struct btree_iter_set);
|
|
|
|
|
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 05:03:40 +08:00
|
|
|
if (!(c->devices = kcalloc(c->nr_uuids, sizeof(void *), GFP_KERNEL)) ||
|
2018-05-21 06:25:51 +08:00
|
|
|
mempool_init_slab_pool(&c->search, 32, bch_search_cache) ||
|
|
|
|
mempool_init_kmalloc_pool(&c->bio_meta, 2,
|
2018-08-11 13:19:47 +08:00
|
|
|
sizeof(struct bbio) + sizeof(struct bio_vec) *
|
|
|
|
bucket_pages(c)) ||
|
2018-05-21 06:25:51 +08:00
|
|
|
mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) ||
|
|
|
|
bioset_init(&c->bio_split, 4, offsetof(struct bbio, bio),
|
|
|
|
BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER) ||
|
2013-03-24 07:11:31 +08:00
|
|
|
!(c->uuids = alloc_bucket_pages(GFP_KERNEL, c)) ||
|
2016-06-08 04:27:19 +08:00
|
|
|
!(c->moving_gc_wq = alloc_workqueue("bcache_gc",
|
|
|
|
WQ_MEM_RECLAIM, 0)) ||
|
2013-03-24 07:11:31 +08:00
|
|
|
bch_journal_alloc(c) ||
|
|
|
|
bch_btree_cache_alloc(c) ||
|
2013-09-11 13:53:34 +08:00
|
|
|
bch_open_buckets_alloc(c) ||
|
|
|
|
bch_bset_sort_state_init(&c->sort, ilog2(c->btree_pages)))
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
c->congested_read_threshold_us = 2000;
|
|
|
|
c->congested_write_threshold_us = 20000;
|
bcache: set error_limit correctly
Struct cache uses io_errors for two purposes,
- Error decay: when cache set error_decay is set, io_errors is used to
generate a small piece of delay when I/O error happens.
- I/O errors counter: in order to generate big enough value for error
decay, I/O errors counter value is stored by left shifting 20 bits (a.k.a
IO_ERROR_SHIFT).
In function bch_count_io_errors(), if I/O errors counter reaches cache set
error limit, bch_cache_set_error() will be called to retire the whold cache
set. But current code is problematic when checking the error limit, see the
following code piece from bch_count_io_errors(),
90 if (error) {
91 char buf[BDEVNAME_SIZE];
92 unsigned errors = atomic_add_return(1 << IO_ERROR_SHIFT,
93 &ca->io_errors);
94 errors >>= IO_ERROR_SHIFT;
95
96 if (errors < ca->set->error_limit)
97 pr_err("%s: IO error on %s, recovering",
98 bdevname(ca->bdev, buf), m);
99 else
100 bch_cache_set_error(ca->set,
101 "%s: too many IO errors %s",
102 bdevname(ca->bdev, buf), m);
103 }
At line 94, errors is right shifting IO_ERROR_SHIFT bits, now it is real
errors counter to compare at line 96. But ca->set->error_limit is initia-
lized with an amplified value in bch_cache_set_alloc(),
1545 c->error_limit = 8 << IO_ERROR_SHIFT;
It means by default, in bch_count_io_errors(), before 8<<20 errors happened
bch_cache_set_error() won't be called to retire the problematic cache
device. If the average request size is 64KB, it means bcache won't handle
failed device until 512GB data is requested. This is too large to be an I/O
threashold. So I believe the correct error limit should be much less.
This patch sets default cache set error limit to 8, then in
bch_count_io_errors() when errors counter reaches 8 (if it is default
value), function bch_cache_set_error() will be called to retire the whole
cache set. This patch also removes bits shifting when store or show
io_error_limit value via sysfs interface.
Nowadays most of SSDs handle internal flash failure automatically by LBA
address re-indirect mapping. If an I/O error can be observed by upper layer
code, it will be a notable error because that SSD can not re-indirect
map the problematic LBA address to an available flash block. This situation
indicates the whole SSD will be failed very soon. Therefore setting 8 as
the default io error limit value makes sense, it is enough for most of
cache devices.
Changelog:
v2: add reviewed-by from Hannes.
v1: initial version for review.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-02-08 03:41:42 +08:00
|
|
|
c->error_limit = DEFAULT_IO_ERROR_LIMIT;
|
bcache: add CACHE_SET_IO_DISABLE to struct cache_set flags
When too many I/Os failed on cache device, bch_cache_set_error() is called
in the error handling code path to retire whole problematic cache set. If
new I/O requests continue to come and take refcount dc->count, the cache
set won't be retired immediately, this is a problem.
Further more, there are several kernel thread and self-armed kernel work
may still running after bch_cache_set_error() is called. It needs to wait
quite a while for them to stop, or they won't stop at all. They also
prevent the cache set from being retired.
The solution in this patch is, to add per cache set flag to disable I/O
request on this cache and all attached backing devices. Then new coming I/O
requests can be rejected in *_make_request() before taking refcount, kernel
threads and self-armed kernel worker can stop very fast when flags bit
CACHE_SET_IO_DISABLE is set.
Because bcache also do internal I/Os for writeback, garbage collection,
bucket allocation, journaling, this kind of I/O should be disabled after
bch_cache_set_error() is called. So closure_bio_submit() is modified to
check whether CACHE_SET_IO_DISABLE is set on cache_set->flags. If set,
closure_bio_submit() will set bio->bi_status to BLK_STS_IOERR and
return, generic_make_request() won't be called.
A sysfs interface is also added to set or clear CACHE_SET_IO_DISABLE bit
from cache_set->flags, to disable or enable cache set I/O for debugging. It
is helpful to trigger more corner case issues for failed cache device.
Changelog
v4, add wait_for_kthread_stop(), and call it before exits writeback and gc
kernel threads.
v3, change CACHE_SET_IO_DISABLE from 4 to 3, since it is bit index.
remove "bcache: " prefix when printing out kernel message.
v2, more changes by previous review,
- Use CACHE_SET_IO_DISABLE of cache_set->flags, suggested by Junhui.
- Check CACHE_SET_IO_DISABLE in bch_btree_gc() to stop a while-loop, this
is reported and inspired from origal patch of Pavel Vazharov.
v1, initial version.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Cc: Junhui Tang <tang.junhui@zte.com.cn>
Cc: Michael Lyle <mlyle@lyle.org>
Cc: Pavel Vazharov <freakpv@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-03-19 08:36:17 +08:00
|
|
|
WARN_ON(test_and_clear_bit(CACHE_SET_IO_DISABLE, &c->flags));
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
return c;
|
|
|
|
err:
|
|
|
|
bch_cache_set_unregister(c);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-04-25 00:48:34 +08:00
|
|
|
static int run_cache_set(struct cache_set *c)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
const char *err = "cannot allocate memory";
|
|
|
|
struct cached_dev *dc, *t;
|
|
|
|
struct cache *ca;
|
2013-07-25 08:44:17 +08:00
|
|
|
struct closure cl;
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2019-04-25 00:48:43 +08:00
|
|
|
LIST_HEAD(journal);
|
|
|
|
struct journal_replay *l;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-07-25 08:44:17 +08:00
|
|
|
closure_init_stack(&cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
for_each_cache(ca, c, i)
|
|
|
|
c->nbuckets += ca->sb.nbuckets;
|
2016-10-27 11:31:17 +08:00
|
|
|
set_gc_sectors(c);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
if (CACHE_SYNC(&c->sb)) {
|
|
|
|
struct bkey *k;
|
|
|
|
struct jset *j;
|
|
|
|
|
|
|
|
err = "cannot allocate memory for journal";
|
2013-07-25 08:44:17 +08:00
|
|
|
if (bch_journal_read(c, &journal))
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
pr_debug("btree_journal_read() done");
|
|
|
|
|
|
|
|
err = "no journal entries found";
|
|
|
|
if (list_empty(&journal))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
j = &list_entry(journal.prev, struct journal_replay, list)->j;
|
|
|
|
|
|
|
|
err = "IO error reading priorities";
|
|
|
|
for_each_cache(ca, c, i)
|
|
|
|
prio_read(ca, j->prio_bucket[ca->sb.nr_this_dev]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If prio_read() fails it'll call cache_set_error and we'll
|
|
|
|
* tear everything down right away, but if we perhaps checked
|
|
|
|
* sooner we could avoid journal replay.
|
|
|
|
*/
|
|
|
|
|
|
|
|
k = &j->btree_root;
|
|
|
|
|
|
|
|
err = "bad btree root";
|
2013-12-21 09:22:05 +08:00
|
|
|
if (__bch_btree_ptr_invalid(c, k))
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
err = "error reading btree root";
|
2018-08-11 13:19:47 +08:00
|
|
|
c->root = bch_btree_node_get(c, NULL, k,
|
|
|
|
j->btree_level,
|
|
|
|
true, NULL);
|
2013-03-24 07:11:31 +08:00
|
|
|
if (IS_ERR_OR_NULL(c->root))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
list_del_init(&c->root->list);
|
|
|
|
rw_unlock(true, c->root);
|
|
|
|
|
2013-07-25 08:44:17 +08:00
|
|
|
err = uuid_read(c, j, &cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
if (err)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
err = "error in recovery";
|
2013-07-25 08:44:17 +08:00
|
|
|
if (bch_btree_check(c))
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
bch_journal_mark(c, &journal);
|
2014-03-18 07:55:55 +08:00
|
|
|
bch_initial_gc_finish(c);
|
2013-03-24 07:11:31 +08:00
|
|
|
pr_debug("btree_check() done");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bcache_journal_next() can't happen sooner, or
|
|
|
|
* btree_gc_finish() will give spurious errors about last_gc >
|
|
|
|
* gc_gen - this is a hack but oh well.
|
|
|
|
*/
|
|
|
|
bch_journal_next(&c->journal);
|
|
|
|
|
2013-04-25 10:01:12 +08:00
|
|
|
err = "error starting allocator thread";
|
2013-03-24 07:11:31 +08:00
|
|
|
for_each_cache(ca, c, i)
|
2013-04-25 10:01:12 +08:00
|
|
|
if (bch_cache_allocator_start(ca))
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First place it's safe to allocate: btree_check() and
|
|
|
|
* btree_gc_finish() have to run before we have buckets to
|
|
|
|
* allocate, and bch_bucket_alloc_set() might cause a journal
|
|
|
|
* entry to be written so bcache_journal_next() has to be called
|
|
|
|
* first.
|
|
|
|
*
|
|
|
|
* If the uuids were in the old format we have to rewrite them
|
|
|
|
* before the next journal entry is written:
|
|
|
|
*/
|
|
|
|
if (j->version < BCACHE_JSET_VERSION_UUID)
|
|
|
|
__uuid_write(c);
|
|
|
|
|
2019-04-25 00:48:34 +08:00
|
|
|
err = "bcache: replay journal failed";
|
|
|
|
if (bch_journal_replay(c, &journal))
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
} else {
|
|
|
|
pr_notice("invalidating existing data");
|
|
|
|
|
|
|
|
for_each_cache(ca, c, i) {
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int j;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
ca->sb.keys = clamp_t(int, ca->sb.nbuckets >> 7,
|
|
|
|
2, SB_JOURNAL_BUCKETS);
|
|
|
|
|
|
|
|
for (j = 0; j < ca->sb.keys; j++)
|
|
|
|
ca->sb.d[j] = ca->sb.first_bucket + j;
|
|
|
|
}
|
|
|
|
|
2014-03-18 07:55:55 +08:00
|
|
|
bch_initial_gc_finish(c);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2013-04-25 10:01:12 +08:00
|
|
|
err = "error starting allocator thread";
|
2013-03-24 07:11:31 +08:00
|
|
|
for_each_cache(ca, c, i)
|
2013-04-25 10:01:12 +08:00
|
|
|
if (bch_cache_allocator_start(ca))
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
mutex_lock(&c->bucket_lock);
|
|
|
|
for_each_cache(ca, c, i)
|
|
|
|
bch_prio_write(ca);
|
|
|
|
mutex_unlock(&c->bucket_lock);
|
|
|
|
|
|
|
|
err = "cannot allocate new UUID bucket";
|
|
|
|
if (__uuid_write(c))
|
2013-10-25 08:19:26 +08:00
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
err = "cannot allocate new btree root";
|
2014-07-12 15:22:53 +08:00
|
|
|
c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL);
|
2013-03-24 07:11:31 +08:00
|
|
|
if (IS_ERR_OR_NULL(c->root))
|
2013-10-25 08:19:26 +08:00
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2014-03-05 08:42:42 +08:00
|
|
|
mutex_lock(&c->root->write_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
bkey_copy_key(&c->root->key, &MAX_KEY);
|
2013-07-25 08:44:17 +08:00
|
|
|
bch_btree_node_write(c->root, &cl);
|
2014-03-05 08:42:42 +08:00
|
|
|
mutex_unlock(&c->root->write_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
bch_btree_set_root(c->root);
|
|
|
|
rw_unlock(true, c->root);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't want to write the first journal entry until
|
|
|
|
* everything is set up - fortunately journal entries won't be
|
|
|
|
* written until the SET_CACHE_SYNC() here:
|
|
|
|
*/
|
|
|
|
SET_CACHE_SYNC(&c->sb, true);
|
|
|
|
|
|
|
|
bch_journal_next(&c->journal);
|
2013-07-25 08:44:17 +08:00
|
|
|
bch_journal_meta(c, &cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
2013-10-25 08:19:26 +08:00
|
|
|
err = "error starting gc thread";
|
|
|
|
if (bch_gc_thread_start(c))
|
|
|
|
goto err;
|
|
|
|
|
2013-07-25 08:44:17 +08:00
|
|
|
closure_sync(&cl);
|
2018-07-26 12:17:41 +08:00
|
|
|
c->sb.last_mount = (u32)ktime_get_real_seconds();
|
2013-03-24 07:11:31 +08:00
|
|
|
bcache_write_super(c);
|
|
|
|
|
|
|
|
list_for_each_entry_safe(dc, t, &uncached_devices, list)
|
bcache: fix for data collapse after re-attaching an attached device
back-end device sdm has already attached a cache_set with ID
f67ebe1f-f8bc-4d73-bfe5-9dc88607f119, then try to attach with
another cache set, and it returns with an error:
[root]# cd /sys/block/sdm/bcache
[root]# echo 5ccd0a63-148e-48b8-afa2-aca9cbd6279f > attach
-bash: echo: write error: Invalid argument
After that, execute a command to modify the label of bcache
device:
[root]# echo data_disk1 > label
Then we reboot the system, when the system power on, the back-end
device can not attach to cache_set, a messages show in the log:
Feb 5 12:05:52 ceph152 kernel: [922385.508498] bcache:
bch_cached_dev_attach() couldn't find uuid for sdm in set
In sysfs_attach(), dc->sb.set_uuid was assigned to the value
which input through sysfs, no matter whether it is success
or not in bch_cached_dev_attach(). For example, If the back-end
device has already attached to an cache set, bch_cached_dev_attach()
would fail, but dc->sb.set_uuid was changed. Then modify the
label of bcache device, it will call bch_write_bdev_super(),
which would write the dc->sb.set_uuid to the super block, so we
record a wrong cache set ID in the super block, after the system
reboot, the cache set couldn't find the uuid of the back-end
device, so the bcache device couldn't exist and use any more.
In this patch, we don't assigned cache set ID to dc->sb.set_uuid
in sysfs_attach() directly, but input it into bch_cached_dev_attach(),
and assigned dc->sb.set_uuid to the cache set ID after the back-end
device attached to the cache set successful.
Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-02-08 03:41:46 +08:00
|
|
|
bch_cached_dev_attach(dc, c, NULL);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
flash_devs_run(c);
|
|
|
|
|
2014-07-12 03:17:41 +08:00
|
|
|
set_bit(CACHE_SET_RUNNING, &c->flags);
|
2019-04-25 00:48:34 +08:00
|
|
|
return 0;
|
2013-03-24 07:11:31 +08:00
|
|
|
err:
|
2019-04-25 00:48:43 +08:00
|
|
|
while (!list_empty(&journal)) {
|
|
|
|
l = list_first_entry(&journal, struct journal_replay, list);
|
|
|
|
list_del(&l->list);
|
|
|
|
kfree(l);
|
|
|
|
}
|
|
|
|
|
2013-07-25 08:44:17 +08:00
|
|
|
closure_sync(&cl);
|
2013-03-24 07:11:31 +08:00
|
|
|
/* XXX: test this, it's broken */
|
2013-09-11 12:41:34 +08:00
|
|
|
bch_cache_set_error(c, "%s", err);
|
2019-04-25 00:48:34 +08:00
|
|
|
|
|
|
|
return -EIO;
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool can_attach_cache(struct cache *ca, struct cache_set *c)
|
|
|
|
{
|
|
|
|
return ca->sb.block_size == c->sb.block_size &&
|
2013-10-23 04:19:23 +08:00
|
|
|
ca->sb.bucket_size == c->sb.bucket_size &&
|
2013-03-24 07:11:31 +08:00
|
|
|
ca->sb.nr_in_set == c->sb.nr_in_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *register_cache_set(struct cache *ca)
|
|
|
|
{
|
|
|
|
char buf[12];
|
|
|
|
const char *err = "cannot allocate memory";
|
|
|
|
struct cache_set *c;
|
|
|
|
|
|
|
|
list_for_each_entry(c, &bch_cache_sets, list)
|
|
|
|
if (!memcmp(c->sb.set_uuid, ca->sb.set_uuid, 16)) {
|
|
|
|
if (c->cache[ca->sb.nr_this_dev])
|
|
|
|
return "duplicate cache set member";
|
|
|
|
|
|
|
|
if (!can_attach_cache(ca, c))
|
|
|
|
return "cache sb does not match set";
|
|
|
|
|
|
|
|
if (!CACHE_SYNC(&ca->sb))
|
|
|
|
SET_CACHE_SYNC(&c->sb, false);
|
|
|
|
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = bch_cache_set_alloc(&ca->sb);
|
|
|
|
if (!c)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
err = "error creating kobject";
|
|
|
|
if (kobject_add(&c->kobj, bcache_kobj, "%pU", c->sb.set_uuid) ||
|
|
|
|
kobject_add(&c->internal, &c->kobj, "internal"))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (bch_cache_accounting_add_kobjs(&c->accounting, &c->kobj))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
bch_debug_init_cache_set(c);
|
|
|
|
|
|
|
|
list_add(&c->list, &bch_cache_sets);
|
|
|
|
found:
|
|
|
|
sprintf(buf, "cache%i", ca->sb.nr_this_dev);
|
|
|
|
if (sysfs_create_link(&ca->kobj, &c->kobj, "set") ||
|
|
|
|
sysfs_create_link(&c->kobj, &ca->kobj, buf))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (ca->sb.seq > c->sb.seq) {
|
|
|
|
c->sb.version = ca->sb.version;
|
|
|
|
memcpy(c->sb.set_uuid, ca->sb.set_uuid, 16);
|
|
|
|
c->sb.flags = ca->sb.flags;
|
|
|
|
c->sb.seq = ca->sb.seq;
|
|
|
|
pr_debug("set version = %llu", c->sb.version);
|
|
|
|
}
|
|
|
|
|
2014-06-12 10:44:49 +08:00
|
|
|
kobject_get(&ca->kobj);
|
2013-03-24 07:11:31 +08:00
|
|
|
ca->set = c;
|
|
|
|
ca->set->cache[ca->sb.nr_this_dev] = ca;
|
|
|
|
c->cache_by_alloc[c->caches_loaded++] = ca;
|
|
|
|
|
2019-04-25 00:48:34 +08:00
|
|
|
if (c->caches_loaded == c->sb.nr_in_set) {
|
|
|
|
err = "failed to run cache set";
|
|
|
|
if (run_cache_set(c) < 0)
|
|
|
|
goto err;
|
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
err:
|
|
|
|
bch_cache_set_unregister(c);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cache device */
|
|
|
|
|
2019-04-25 00:48:35 +08:00
|
|
|
/* When ca->kobj released */
|
2013-03-24 07:11:31 +08:00
|
|
|
void bch_cache_release(struct kobject *kobj)
|
|
|
|
{
|
|
|
|
struct cache *ca = container_of(kobj, struct cache, kobj);
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2014-06-20 06:05:59 +08:00
|
|
|
if (ca->set) {
|
|
|
|
BUG_ON(ca->set->cache[ca->sb.nr_this_dev] != ca);
|
2013-03-24 07:11:31 +08:00
|
|
|
ca->set->cache[ca->sb.nr_this_dev] = NULL;
|
2014-06-20 06:05:59 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
free_pages((unsigned long) ca->disk_buckets, ilog2(bucket_pages(ca)));
|
|
|
|
kfree(ca->prio_buckets);
|
|
|
|
vfree(ca->buckets);
|
|
|
|
|
|
|
|
free_heap(&ca->heap);
|
|
|
|
free_fifo(&ca->free_inc);
|
2013-12-17 17:29:34 +08:00
|
|
|
|
|
|
|
for (i = 0; i < RESERVE_NR; i++)
|
|
|
|
free_fifo(&ca->free[i]);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
if (ca->sb_bio.bi_inline_vecs[0].bv_page)
|
2017-12-18 20:22:04 +08:00
|
|
|
put_page(bio_first_page_all(&ca->sb_bio));
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2014-07-08 04:03:36 +08:00
|
|
|
if (!IS_ERR_OR_NULL(ca->bdev))
|
2013-03-24 07:11:31 +08:00
|
|
|
blkdev_put(ca->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
|
|
|
|
|
|
|
|
kfree(ca);
|
|
|
|
module_put(THIS_MODULE);
|
|
|
|
}
|
|
|
|
|
2016-07-04 09:23:25 +08:00
|
|
|
static int cache_alloc(struct cache *ca)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
|
|
|
size_t free;
|
bcache: fix for allocator and register thread race
After long time running of random small IO writing,
I reboot the machine, and after the machine power on,
I found bcache got stuck, the stack is:
[root@ceph153 ~]# cat /proc/2510/task/*/stack
[<ffffffffa06b2455>] closure_sync+0x25/0x90 [bcache]
[<ffffffffa06b6be8>] bch_journal+0x118/0x2b0 [bcache]
[<ffffffffa06b6dc7>] bch_journal_meta+0x47/0x70 [bcache]
[<ffffffffa06be8f7>] bch_prio_write+0x237/0x340 [bcache]
[<ffffffffa06a8018>] bch_allocator_thread+0x3c8/0x3d0 [bcache]
[<ffffffff810a631f>] kthread+0xcf/0xe0
[<ffffffff8164c318>] ret_from_fork+0x58/0x90
[<ffffffffffffffff>] 0xffffffffffffffff
[root@ceph153 ~]# cat /proc/2038/task/*/stack
[<ffffffffa06b1abd>] __bch_btree_map_nodes+0x12d/0x150 [bcache]
[<ffffffffa06b1bd1>] bch_btree_insert+0xf1/0x170 [bcache]
[<ffffffffa06b637f>] bch_journal_replay+0x13f/0x230 [bcache]
[<ffffffffa06c75fe>] run_cache_set+0x79a/0x7c2 [bcache]
[<ffffffffa06c0cf8>] register_bcache+0xd48/0x1310 [bcache]
[<ffffffff812f702f>] kobj_attr_store+0xf/0x20
[<ffffffff8125b216>] sysfs_write_file+0xc6/0x140
[<ffffffff811dfbfd>] vfs_write+0xbd/0x1e0
[<ffffffff811e069f>] SyS_write+0x7f/0xe0
[<ffffffff8164c3c9>] system_call_fastpath+0x16/0x1
The stack shows the register thread and allocator thread
were getting stuck when registering cache device.
I reboot the machine several times, the issue always
exsit in this machine.
I debug the code, and found the call trace as bellow:
register_bcache()
==>run_cache_set()
==>bch_journal_replay()
==>bch_btree_insert()
==>__bch_btree_map_nodes()
==>btree_insert_fn()
==>btree_split() //node need split
==>btree_check_reserve()
In btree_check_reserve(), It will check if there is enough buckets
of RESERVE_BTREE type, since allocator thread did not work yet, so
no buckets of RESERVE_BTREE type allocated, so the register thread
waits on c->btree_cache_wait, and goes to sleep.
Then the allocator thread initialized, the call trace is bellow:
bch_allocator_thread()
==>bch_prio_write()
==>bch_journal_meta()
==>bch_journal()
==>journal_wait_for_write()
In journal_wait_for_write(), It will check if journal is full by
journal_full(), but the long time random small IO writing
causes the exhaustion of journal buckets(journal.blocks_free=0),
In order to release the journal buckets,
the allocator calls btree_flush_write() to flush keys to
btree nodes, and waits on c->journal.wait until btree nodes writing
over or there has already some journal buckets space, then the
allocator thread goes to sleep. but in btree_flush_write(), since
bch_journal_replay() is not finished, so no btree nodes have journal
(condition "if (btree_current_write(b)->journal)" never satisfied),
so we got no btree node to flush, no journal bucket released,
and allocator sleep all the times.
Through the above analysis, we can see that:
1) Register thread wait for allocator thread to allocate buckets of
RESERVE_BTREE type;
2) Alloctor thread wait for register thread to replay journal, so it
can flush btree nodes and get journal bucket.
then they are all got stuck by waiting for each other.
Hua Rui provided a patch for me, by allocating some buckets of
RESERVE_BTREE type in advance, so the register thread can get bucket
when btree node splitting and no need to waiting for the allocator
thread. I tested it, it has effect, and register thread run a step
forward, but finally are still got stuck, the reason is only 8 bucket
of RESERVE_BTREE type were allocated, and in bch_journal_replay(),
after 2 btree nodes splitting, only 4 bucket of RESERVE_BTREE type left,
then btree_check_reserve() is not satisfied anymore, so it goes to sleep
again, and in the same time, alloctor thread did not flush enough btree
nodes to release a journal bucket, so they all got stuck again.
So we need to allocate more buckets of RESERVE_BTREE type in advance,
but how much is enough? By experience and test, I think it should be
as much as journal buckets. Then I modify the code as this patch,
and test in the machine, and it works.
This patch modified base on Hua Rui’s patch, and allocate more buckets
of RESERVE_BTREE type in advance to avoid register thread and allocate
thread going to wait for each other.
[patch v2] ca->sb.njournal_buckets would be 0 in the first time after
cache creation, and no journal exists, so just 8 btree buckets is OK.
Signed-off-by: Hua Rui <huarui.dev@gmail.com>
Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-02-08 03:41:43 +08:00
|
|
|
size_t btree_buckets;
|
2013-03-24 07:11:31 +08:00
|
|
|
struct bucket *b;
|
2018-10-08 20:41:20 +08:00
|
|
|
int ret = -ENOMEM;
|
|
|
|
const char *err = NULL;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
__module_get(THIS_MODULE);
|
|
|
|
kobject_init(&ca->kobj, &bch_cache_ktype);
|
|
|
|
|
2016-11-22 23:57:21 +08:00
|
|
|
bio_init(&ca->journal.bio, ca->journal.bio.bi_inline_vecs, 8);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
bcache: fix for allocator and register thread race
After long time running of random small IO writing,
I reboot the machine, and after the machine power on,
I found bcache got stuck, the stack is:
[root@ceph153 ~]# cat /proc/2510/task/*/stack
[<ffffffffa06b2455>] closure_sync+0x25/0x90 [bcache]
[<ffffffffa06b6be8>] bch_journal+0x118/0x2b0 [bcache]
[<ffffffffa06b6dc7>] bch_journal_meta+0x47/0x70 [bcache]
[<ffffffffa06be8f7>] bch_prio_write+0x237/0x340 [bcache]
[<ffffffffa06a8018>] bch_allocator_thread+0x3c8/0x3d0 [bcache]
[<ffffffff810a631f>] kthread+0xcf/0xe0
[<ffffffff8164c318>] ret_from_fork+0x58/0x90
[<ffffffffffffffff>] 0xffffffffffffffff
[root@ceph153 ~]# cat /proc/2038/task/*/stack
[<ffffffffa06b1abd>] __bch_btree_map_nodes+0x12d/0x150 [bcache]
[<ffffffffa06b1bd1>] bch_btree_insert+0xf1/0x170 [bcache]
[<ffffffffa06b637f>] bch_journal_replay+0x13f/0x230 [bcache]
[<ffffffffa06c75fe>] run_cache_set+0x79a/0x7c2 [bcache]
[<ffffffffa06c0cf8>] register_bcache+0xd48/0x1310 [bcache]
[<ffffffff812f702f>] kobj_attr_store+0xf/0x20
[<ffffffff8125b216>] sysfs_write_file+0xc6/0x140
[<ffffffff811dfbfd>] vfs_write+0xbd/0x1e0
[<ffffffff811e069f>] SyS_write+0x7f/0xe0
[<ffffffff8164c3c9>] system_call_fastpath+0x16/0x1
The stack shows the register thread and allocator thread
were getting stuck when registering cache device.
I reboot the machine several times, the issue always
exsit in this machine.
I debug the code, and found the call trace as bellow:
register_bcache()
==>run_cache_set()
==>bch_journal_replay()
==>bch_btree_insert()
==>__bch_btree_map_nodes()
==>btree_insert_fn()
==>btree_split() //node need split
==>btree_check_reserve()
In btree_check_reserve(), It will check if there is enough buckets
of RESERVE_BTREE type, since allocator thread did not work yet, so
no buckets of RESERVE_BTREE type allocated, so the register thread
waits on c->btree_cache_wait, and goes to sleep.
Then the allocator thread initialized, the call trace is bellow:
bch_allocator_thread()
==>bch_prio_write()
==>bch_journal_meta()
==>bch_journal()
==>journal_wait_for_write()
In journal_wait_for_write(), It will check if journal is full by
journal_full(), but the long time random small IO writing
causes the exhaustion of journal buckets(journal.blocks_free=0),
In order to release the journal buckets,
the allocator calls btree_flush_write() to flush keys to
btree nodes, and waits on c->journal.wait until btree nodes writing
over or there has already some journal buckets space, then the
allocator thread goes to sleep. but in btree_flush_write(), since
bch_journal_replay() is not finished, so no btree nodes have journal
(condition "if (btree_current_write(b)->journal)" never satisfied),
so we got no btree node to flush, no journal bucket released,
and allocator sleep all the times.
Through the above analysis, we can see that:
1) Register thread wait for allocator thread to allocate buckets of
RESERVE_BTREE type;
2) Alloctor thread wait for register thread to replay journal, so it
can flush btree nodes and get journal bucket.
then they are all got stuck by waiting for each other.
Hua Rui provided a patch for me, by allocating some buckets of
RESERVE_BTREE type in advance, so the register thread can get bucket
when btree node splitting and no need to waiting for the allocator
thread. I tested it, it has effect, and register thread run a step
forward, but finally are still got stuck, the reason is only 8 bucket
of RESERVE_BTREE type were allocated, and in bch_journal_replay(),
after 2 btree nodes splitting, only 4 bucket of RESERVE_BTREE type left,
then btree_check_reserve() is not satisfied anymore, so it goes to sleep
again, and in the same time, alloctor thread did not flush enough btree
nodes to release a journal bucket, so they all got stuck again.
So we need to allocate more buckets of RESERVE_BTREE type in advance,
but how much is enough? By experience and test, I think it should be
as much as journal buckets. Then I modify the code as this patch,
and test in the machine, and it works.
This patch modified base on Hua Rui’s patch, and allocate more buckets
of RESERVE_BTREE type in advance to avoid register thread and allocate
thread going to wait for each other.
[patch v2] ca->sb.njournal_buckets would be 0 in the first time after
cache creation, and no journal exists, so just 8 btree buckets is OK.
Signed-off-by: Hua Rui <huarui.dev@gmail.com>
Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2018-02-08 03:41:43 +08:00
|
|
|
/*
|
|
|
|
* when ca->sb.njournal_buckets is not zero, journal exists,
|
|
|
|
* and in bch_journal_replay(), tree node may split,
|
|
|
|
* so bucket of RESERVE_BTREE type is needed,
|
|
|
|
* the worst situation is all journal buckets are valid journal,
|
|
|
|
* and all the keys need to replay,
|
|
|
|
* so the number of RESERVE_BTREE type buckets should be as much
|
|
|
|
* as journal buckets
|
|
|
|
*/
|
|
|
|
btree_buckets = ca->sb.njournal_buckets ?: 8;
|
2013-12-17 17:29:34 +08:00
|
|
|
free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
|
2018-10-08 20:41:21 +08:00
|
|
|
if (!free) {
|
|
|
|
ret = -EPERM;
|
|
|
|
err = "ca->sb.nbuckets is too small";
|
|
|
|
goto err_free;
|
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-10-08 20:41:20 +08:00
|
|
|
if (!init_fifo(&ca->free[RESERVE_BTREE], btree_buckets,
|
|
|
|
GFP_KERNEL)) {
|
|
|
|
err = "ca->free[RESERVE_BTREE] alloc failed";
|
|
|
|
goto err_btree_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!init_fifo_exact(&ca->free[RESERVE_PRIO], prio_buckets(ca),
|
|
|
|
GFP_KERNEL)) {
|
|
|
|
err = "ca->free[RESERVE_PRIO] alloc failed";
|
|
|
|
goto err_prio_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL)) {
|
|
|
|
err = "ca->free[RESERVE_MOVINGGC] alloc failed";
|
|
|
|
goto err_movinggc_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL)) {
|
|
|
|
err = "ca->free[RESERVE_NONE] alloc failed";
|
|
|
|
goto err_none_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!init_fifo(&ca->free_inc, free << 2, GFP_KERNEL)) {
|
|
|
|
err = "ca->free_inc alloc failed";
|
|
|
|
goto err_free_inc_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!init_heap(&ca->heap, free << 3, GFP_KERNEL)) {
|
|
|
|
err = "ca->heap alloc failed";
|
|
|
|
goto err_heap_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
ca->buckets = vzalloc(array_size(sizeof(struct bucket),
|
|
|
|
ca->sb.nbuckets));
|
|
|
|
if (!ca->buckets) {
|
|
|
|
err = "ca->buckets alloc failed";
|
|
|
|
goto err_buckets_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
ca->prio_buckets = kzalloc(array3_size(sizeof(uint64_t),
|
|
|
|
prio_buckets(ca), 2),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!ca->prio_buckets) {
|
|
|
|
err = "ca->prio_buckets alloc failed";
|
|
|
|
goto err_prio_buckets_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
ca->disk_buckets = alloc_bucket_pages(GFP_KERNEL, ca);
|
|
|
|
if (!ca->disk_buckets) {
|
|
|
|
err = "ca->disk_buckets alloc failed";
|
|
|
|
goto err_disk_buckets_alloc;
|
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
ca->prio_last_buckets = ca->prio_buckets + prio_buckets(ca);
|
|
|
|
|
|
|
|
for_each_bucket(b, ca)
|
|
|
|
atomic_set(&b->pin, 0);
|
|
|
|
return 0;
|
2018-10-08 20:41:20 +08:00
|
|
|
|
|
|
|
err_disk_buckets_alloc:
|
|
|
|
kfree(ca->prio_buckets);
|
|
|
|
err_prio_buckets_alloc:
|
|
|
|
vfree(ca->buckets);
|
|
|
|
err_buckets_alloc:
|
|
|
|
free_heap(&ca->heap);
|
|
|
|
err_heap_alloc:
|
|
|
|
free_fifo(&ca->free_inc);
|
|
|
|
err_free_inc_alloc:
|
|
|
|
free_fifo(&ca->free[RESERVE_NONE]);
|
|
|
|
err_none_alloc:
|
|
|
|
free_fifo(&ca->free[RESERVE_MOVINGGC]);
|
|
|
|
err_movinggc_alloc:
|
|
|
|
free_fifo(&ca->free[RESERVE_PRIO]);
|
|
|
|
err_prio_alloc:
|
|
|
|
free_fifo(&ca->free[RESERVE_BTREE]);
|
|
|
|
err_btree_alloc:
|
2018-10-08 20:41:21 +08:00
|
|
|
err_free:
|
2018-10-08 20:41:20 +08:00
|
|
|
module_put(THIS_MODULE);
|
|
|
|
if (err)
|
|
|
|
pr_notice("error %s: %s", ca->cache_dev_name, err);
|
|
|
|
return ret;
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
2016-02-27 06:33:56 +08:00
|
|
|
static int register_cache(struct cache_sb *sb, struct page *sb_page,
|
2014-06-20 06:05:59 +08:00
|
|
|
struct block_device *bdev, struct cache *ca)
|
2013-03-24 07:11:31 +08:00
|
|
|
{
|
2016-06-18 06:01:54 +08:00
|
|
|
const char *err = NULL; /* must be set for any error case */
|
2016-02-27 06:33:56 +08:00
|
|
|
int ret = 0;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-05-03 18:51:32 +08:00
|
|
|
bdevname(bdev, ca->cache_dev_name);
|
2013-05-15 15:11:26 +08:00
|
|
|
memcpy(&ca->sb, sb, sizeof(struct cache_sb));
|
2013-03-24 07:11:31 +08:00
|
|
|
ca->bdev = bdev;
|
|
|
|
ca->bdev->bd_holder = ca;
|
|
|
|
|
2016-11-22 23:57:21 +08:00
|
|
|
bio_init(&ca->sb_bio, ca->sb_bio.bi_inline_vecs, 1);
|
2017-12-18 20:22:04 +08:00
|
|
|
bio_first_bvec_all(&ca->sb_bio)->bv_page = sb_page;
|
2013-05-15 15:11:26 +08:00
|
|
|
get_page(sb_page);
|
|
|
|
|
2018-03-06 05:41:54 +08:00
|
|
|
if (blk_queue_discard(bdev_get_queue(bdev)))
|
2013-03-24 07:11:31 +08:00
|
|
|
ca->discard = CACHE_DISCARD(&ca->sb);
|
|
|
|
|
2016-07-04 09:23:25 +08:00
|
|
|
ret = cache_alloc(ca);
|
2016-06-18 06:01:54 +08:00
|
|
|
if (ret != 0) {
|
2019-04-25 00:48:38 +08:00
|
|
|
/*
|
|
|
|
* If we failed here, it means ca->kobj is not initialized yet,
|
|
|
|
* kobject_put() won't be called and there is no chance to
|
|
|
|
* call blkdev_put() to bdev in bch_cache_release(). So we
|
|
|
|
* explicitly call blkdev_put() here.
|
|
|
|
*/
|
2018-03-06 05:41:54 +08:00
|
|
|
blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
|
2016-06-18 06:01:54 +08:00
|
|
|
if (ret == -ENOMEM)
|
|
|
|
err = "cache_alloc(): -ENOMEM";
|
2018-10-08 20:41:21 +08:00
|
|
|
else if (ret == -EPERM)
|
|
|
|
err = "cache_alloc(): cache device is too small";
|
2016-06-18 06:01:54 +08:00
|
|
|
else
|
|
|
|
err = "cache_alloc(): unknown error";
|
2013-05-15 15:11:26 +08:00
|
|
|
goto err;
|
2016-06-18 06:01:54 +08:00
|
|
|
}
|
2013-05-15 15:11:26 +08:00
|
|
|
|
2018-08-11 13:19:47 +08:00
|
|
|
if (kobject_add(&ca->kobj,
|
|
|
|
&part_to_dev(bdev->bd_part)->kobj,
|
|
|
|
"bcache")) {
|
2016-02-27 06:33:56 +08:00
|
|
|
err = "error calling kobject_add";
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2014-03-18 09:58:55 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
err = register_cache_set(ca);
|
2014-03-18 09:58:55 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
|
2016-02-27 06:33:56 +08:00
|
|
|
if (err) {
|
|
|
|
ret = -ENODEV;
|
|
|
|
goto out;
|
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_info("registered cache device %s", ca->cache_dev_name);
|
2016-02-27 06:33:56 +08:00
|
|
|
|
2014-06-12 10:44:49 +08:00
|
|
|
out:
|
|
|
|
kobject_put(&ca->kobj);
|
2016-02-27 06:33:56 +08:00
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
err:
|
2016-02-27 06:33:56 +08:00
|
|
|
if (err)
|
2018-05-03 18:51:32 +08:00
|
|
|
pr_notice("error %s: %s", ca->cache_dev_name, err);
|
2016-02-27 06:33:56 +08:00
|
|
|
|
|
|
|
return ret;
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Global interfaces/init */
|
|
|
|
|
2018-08-11 13:19:46 +08:00
|
|
|
static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
|
|
|
|
const char *buffer, size_t size);
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
kobj_attribute_write(register, register_bcache);
|
|
|
|
kobj_attribute_write(register_quiet, register_bcache);
|
|
|
|
|
2018-08-11 13:19:57 +08:00
|
|
|
static bool bch_is_open_backing(struct block_device *bdev)
|
|
|
|
{
|
2013-05-04 18:19:41 +08:00
|
|
|
struct cache_set *c, *tc;
|
|
|
|
struct cached_dev *dc, *t;
|
|
|
|
|
|
|
|
list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
|
|
|
|
list_for_each_entry_safe(dc, t, &c->cached_devs, list)
|
|
|
|
if (dc->bdev == bdev)
|
|
|
|
return true;
|
|
|
|
list_for_each_entry_safe(dc, t, &uncached_devices, list)
|
|
|
|
if (dc->bdev == bdev)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-11 13:19:57 +08:00
|
|
|
static bool bch_is_open_cache(struct block_device *bdev)
|
|
|
|
{
|
2013-05-04 18:19:41 +08:00
|
|
|
struct cache_set *c, *tc;
|
|
|
|
struct cache *ca;
|
2018-08-11 13:19:44 +08:00
|
|
|
unsigned int i;
|
2013-05-04 18:19:41 +08:00
|
|
|
|
|
|
|
list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
|
|
|
|
for_each_cache(ca, c, i)
|
|
|
|
if (ca->bdev == bdev)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-11 13:19:57 +08:00
|
|
|
static bool bch_is_open(struct block_device *bdev)
|
|
|
|
{
|
2013-05-04 18:19:41 +08:00
|
|
|
return bch_is_open_cache(bdev) || bch_is_open_backing(bdev);
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
|
|
|
|
const char *buffer, size_t size)
|
|
|
|
{
|
2019-04-25 00:48:37 +08:00
|
|
|
ssize_t ret = -EINVAL;
|
2013-03-24 07:11:31 +08:00
|
|
|
const char *err = "cannot allocate memory";
|
|
|
|
char *path = NULL;
|
|
|
|
struct cache_sb *sb = NULL;
|
|
|
|
struct block_device *bdev = NULL;
|
|
|
|
struct page *sb_page = NULL;
|
|
|
|
|
|
|
|
if (!try_module_get(THIS_MODULE))
|
|
|
|
return -EBUSY;
|
|
|
|
|
2018-07-26 12:17:37 +08:00
|
|
|
path = kstrndup(buffer, size, GFP_KERNEL);
|
|
|
|
if (!path)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
sb = kmalloc(sizeof(struct cache_sb), GFP_KERNEL);
|
|
|
|
if (!sb)
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
err = "failed to open device";
|
|
|
|
bdev = blkdev_get_by_path(strim(path),
|
|
|
|
FMODE_READ|FMODE_WRITE|FMODE_EXCL,
|
|
|
|
sb);
|
2013-05-15 15:11:26 +08:00
|
|
|
if (IS_ERR(bdev)) {
|
2013-05-04 18:19:41 +08:00
|
|
|
if (bdev == ERR_PTR(-EBUSY)) {
|
|
|
|
bdev = lookup_bdev(strim(path));
|
2014-07-14 00:08:59 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2013-05-04 18:19:41 +08:00
|
|
|
if (!IS_ERR(bdev) && bch_is_open(bdev))
|
|
|
|
err = "device already registered";
|
|
|
|
else
|
|
|
|
err = "device busy";
|
2014-07-14 00:08:59 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
2017-09-06 14:25:51 +08:00
|
|
|
if (!IS_ERR(bdev))
|
|
|
|
bdput(bdev);
|
2015-11-30 10:40:23 +08:00
|
|
|
if (attr == &ksysfs_register_quiet)
|
2019-04-25 00:48:37 +08:00
|
|
|
goto quiet_out;
|
2013-05-04 18:19:41 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
2013-05-15 15:11:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
err = "failed to set blocksize";
|
|
|
|
if (set_blocksize(bdev, 4096))
|
|
|
|
goto err_close;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
|
|
|
err = read_super(sb, bdev, &sb_page);
|
|
|
|
if (err)
|
|
|
|
goto err_close;
|
|
|
|
|
2018-03-06 05:41:54 +08:00
|
|
|
err = "failed to register device";
|
2013-04-12 06:14:35 +08:00
|
|
|
if (SB_IS_BDEV(sb)) {
|
2013-03-24 07:11:31 +08:00
|
|
|
struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-05-15 15:11:26 +08:00
|
|
|
if (!dc)
|
|
|
|
goto err_close;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2014-03-18 09:58:55 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2019-04-25 00:48:37 +08:00
|
|
|
ret = register_bdev(sb, sb_page, bdev, dc);
|
2014-03-18 09:58:55 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
2019-04-25 00:48:38 +08:00
|
|
|
/* blkdev_put() will be called in cached_dev_free() */
|
2019-04-25 00:48:37 +08:00
|
|
|
if (ret < 0)
|
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
} else {
|
|
|
|
struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
|
2018-08-11 13:19:45 +08:00
|
|
|
|
2013-05-15 15:11:26 +08:00
|
|
|
if (!ca)
|
|
|
|
goto err_close;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2019-04-25 00:48:38 +08:00
|
|
|
/* blkdev_put() will be called in bch_cache_release() */
|
2016-02-27 06:33:56 +08:00
|
|
|
if (register_cache(sb, sb_page, bdev, ca) != 0)
|
2018-03-06 05:41:54 +08:00
|
|
|
goto err;
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
2019-04-25 00:48:37 +08:00
|
|
|
quiet_out:
|
|
|
|
ret = size;
|
2013-05-15 15:11:26 +08:00
|
|
|
out:
|
|
|
|
if (sb_page)
|
2013-03-24 07:11:31 +08:00
|
|
|
put_page(sb_page);
|
|
|
|
kfree(sb);
|
|
|
|
kfree(path);
|
|
|
|
module_put(THIS_MODULE);
|
|
|
|
return ret;
|
2013-05-15 15:11:26 +08:00
|
|
|
|
|
|
|
err_close:
|
|
|
|
blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
|
|
|
|
err:
|
2018-03-06 05:41:54 +08:00
|
|
|
pr_info("error %s: %s", path, err);
|
2013-05-15 15:11:26 +08:00
|
|
|
goto out;
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
|
|
|
|
{
|
|
|
|
if (code == SYS_DOWN ||
|
|
|
|
code == SYS_HALT ||
|
|
|
|
code == SYS_POWER_OFF) {
|
|
|
|
DEFINE_WAIT(wait);
|
|
|
|
unsigned long start = jiffies;
|
|
|
|
bool stopped = false;
|
|
|
|
|
|
|
|
struct cache_set *c, *tc;
|
|
|
|
struct cached_dev *dc, *tdc;
|
|
|
|
|
|
|
|
mutex_lock(&bch_register_lock);
|
|
|
|
|
|
|
|
if (list_empty(&bch_cache_sets) &&
|
|
|
|
list_empty(&uncached_devices))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
pr_info("Stopping all devices:");
|
|
|
|
|
|
|
|
list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
|
|
|
|
bch_cache_set_stop(c);
|
|
|
|
|
|
|
|
list_for_each_entry_safe(dc, tdc, &uncached_devices, list)
|
|
|
|
bcache_device_stop(&dc->disk);
|
|
|
|
|
2019-04-25 00:48:40 +08:00
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Give an early chance for other kthreads and
|
|
|
|
* kworkers to stop themselves
|
|
|
|
*/
|
|
|
|
schedule();
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
/* What's a condition variable? */
|
|
|
|
while (1) {
|
2019-04-25 00:48:40 +08:00
|
|
|
long timeout = start + 10 * HZ - jiffies;
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2019-04-25 00:48:40 +08:00
|
|
|
mutex_lock(&bch_register_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
stopped = list_empty(&bch_cache_sets) &&
|
|
|
|
list_empty(&uncached_devices);
|
|
|
|
|
|
|
|
if (timeout < 0 || stopped)
|
|
|
|
break;
|
|
|
|
|
|
|
|
prepare_to_wait(&unregister_wait, &wait,
|
|
|
|
TASK_UNINTERRUPTIBLE);
|
|
|
|
|
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
schedule_timeout(timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
finish_wait(&unregister_wait, &wait);
|
|
|
|
|
|
|
|
if (stopped)
|
|
|
|
pr_info("All devices stopped");
|
|
|
|
else
|
|
|
|
pr_notice("Timeout waiting for devices to be closed");
|
|
|
|
out:
|
|
|
|
mutex_unlock(&bch_register_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NOTIFY_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct notifier_block reboot = {
|
|
|
|
.notifier_call = bcache_reboot,
|
|
|
|
.priority = INT_MAX, /* before any real devices */
|
|
|
|
};
|
|
|
|
|
|
|
|
static void bcache_exit(void)
|
|
|
|
{
|
|
|
|
bch_debug_exit();
|
|
|
|
bch_request_exit();
|
|
|
|
if (bcache_kobj)
|
|
|
|
kobject_put(bcache_kobj);
|
|
|
|
if (bcache_wq)
|
|
|
|
destroy_workqueue(bcache_wq);
|
2018-09-27 23:41:46 +08:00
|
|
|
if (bch_journal_wq)
|
|
|
|
destroy_workqueue(bch_journal_wq);
|
|
|
|
|
2013-07-09 08:53:26 +08:00
|
|
|
if (bcache_major)
|
|
|
|
unregister_blkdev(bcache_major, "bcache");
|
2013-03-24 07:11:31 +08:00
|
|
|
unregister_reboot_notifier(&reboot);
|
2017-10-31 05:46:35 +08:00
|
|
|
mutex_destroy(&bch_register_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
}
|
|
|
|
|
2018-12-13 22:53:55 +08:00
|
|
|
/* Check and fixup module parameters */
|
|
|
|
static void check_module_parameters(void)
|
|
|
|
{
|
|
|
|
if (bch_cutoff_writeback_sync == 0)
|
|
|
|
bch_cutoff_writeback_sync = CUTOFF_WRITEBACK_SYNC;
|
|
|
|
else if (bch_cutoff_writeback_sync > CUTOFF_WRITEBACK_SYNC_MAX) {
|
|
|
|
pr_warn("set bch_cutoff_writeback_sync (%u) to max value %u",
|
|
|
|
bch_cutoff_writeback_sync, CUTOFF_WRITEBACK_SYNC_MAX);
|
|
|
|
bch_cutoff_writeback_sync = CUTOFF_WRITEBACK_SYNC_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bch_cutoff_writeback == 0)
|
|
|
|
bch_cutoff_writeback = CUTOFF_WRITEBACK;
|
|
|
|
else if (bch_cutoff_writeback > CUTOFF_WRITEBACK_MAX) {
|
|
|
|
pr_warn("set bch_cutoff_writeback (%u) to max value %u",
|
|
|
|
bch_cutoff_writeback, CUTOFF_WRITEBACK_MAX);
|
|
|
|
bch_cutoff_writeback = CUTOFF_WRITEBACK_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bch_cutoff_writeback > bch_cutoff_writeback_sync) {
|
|
|
|
pr_warn("set bch_cutoff_writeback (%u) to %u",
|
|
|
|
bch_cutoff_writeback, bch_cutoff_writeback_sync);
|
|
|
|
bch_cutoff_writeback = bch_cutoff_writeback_sync;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
static int __init bcache_init(void)
|
|
|
|
{
|
|
|
|
static const struct attribute *files[] = {
|
|
|
|
&ksysfs_register.attr,
|
|
|
|
&ksysfs_register_quiet.attr,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-12-13 22:53:55 +08:00
|
|
|
check_module_parameters();
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
mutex_init(&bch_register_lock);
|
|
|
|
init_waitqueue_head(&unregister_wait);
|
|
|
|
register_reboot_notifier(&reboot);
|
|
|
|
|
|
|
|
bcache_major = register_blkdev(0, "bcache");
|
2015-11-30 09:21:57 +08:00
|
|
|
if (bcache_major < 0) {
|
|
|
|
unregister_reboot_notifier(&reboot);
|
2017-10-31 05:46:35 +08:00
|
|
|
mutex_destroy(&bch_register_lock);
|
2013-03-24 07:11:31 +08:00
|
|
|
return bcache_major;
|
2015-11-30 09:21:57 +08:00
|
|
|
}
|
2013-03-24 07:11:31 +08:00
|
|
|
|
2018-07-26 12:17:39 +08:00
|
|
|
bcache_wq = alloc_workqueue("bcache", WQ_MEM_RECLAIM, 0);
|
|
|
|
if (!bcache_wq)
|
|
|
|
goto err;
|
|
|
|
|
2018-09-27 23:41:46 +08:00
|
|
|
bch_journal_wq = alloc_workqueue("bch_journal", WQ_MEM_RECLAIM, 0);
|
|
|
|
if (!bch_journal_wq)
|
|
|
|
goto err;
|
|
|
|
|
2018-07-26 12:17:39 +08:00
|
|
|
bcache_kobj = kobject_create_and_add("bcache", fs_kobj);
|
|
|
|
if (!bcache_kobj)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (bch_request_init() ||
|
2017-10-31 05:46:35 +08:00
|
|
|
sysfs_create_files(bcache_kobj, files))
|
2013-03-24 07:11:31 +08:00
|
|
|
goto err;
|
|
|
|
|
2018-10-08 20:41:17 +08:00
|
|
|
bch_debug_init();
|
2018-08-09 15:48:42 +08:00
|
|
|
closure_debug_init();
|
|
|
|
|
2013-03-24 07:11:31 +08:00
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
bcache_exit();
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2018-12-13 22:53:55 +08:00
|
|
|
/*
|
|
|
|
* Module hooks
|
|
|
|
*/
|
2013-03-24 07:11:31 +08:00
|
|
|
module_exit(bcache_exit);
|
|
|
|
module_init(bcache_init);
|
2018-12-13 22:53:54 +08:00
|
|
|
|
2018-12-13 22:53:55 +08:00
|
|
|
module_param(bch_cutoff_writeback, uint, 0);
|
|
|
|
MODULE_PARM_DESC(bch_cutoff_writeback, "threshold to cutoff writeback");
|
|
|
|
|
|
|
|
module_param(bch_cutoff_writeback_sync, uint, 0);
|
|
|
|
MODULE_PARM_DESC(bch_cutoff_writeback_sync, "hard threshold to cutoff writeback");
|
|
|
|
|
2018-12-13 22:53:54 +08:00
|
|
|
MODULE_DESCRIPTION("Bcache: a Linux block layer cache");
|
|
|
|
MODULE_AUTHOR("Kent Overstreet <kent.overstreet@gmail.com>");
|
|
|
|
MODULE_LICENSE("GPL");
|