summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2017-02-02 16:38:10 -0900
committerKent Overstreet <kent.overstreet@gmail.com>2017-02-06 20:43:39 -0900
commit53cbdcd2d4b1eaa205ff76b91204049d4c314342 (patch)
tree9606c5f1610cc209ed72a800115a765cfc280b34
parentc8f34d5c7c93d19023a20e612455e91a5775f0e3 (diff)
bcache: Add an internal option to disable all filesystem changes
will be used by fsck
-rw-r--r--drivers/md/bcache/alloc.c3
-rw-r--r--drivers/md/bcache/btree_cache.c3
-rw-r--r--drivers/md/bcache/btree_io.c5
-rw-r--r--drivers/md/bcache/btree_types.h2
-rw-r--r--drivers/md/bcache/debug.c3
-rw-r--r--drivers/md/bcache/io.c5
-rw-r--r--drivers/md/bcache/journal.c13
-rw-r--r--drivers/md/bcache/movinggc.c3
-rw-r--r--drivers/md/bcache/opts.h6
-rw-r--r--drivers/md/bcache/super.c34
-rw-r--r--drivers/md/bcache/tier.c3
11 files changed, 65 insertions, 15 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index cff750c00852..4fe08b571893 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -254,6 +254,9 @@ static int bch_prio_write(struct cache *ca)
bool need_new_journal_entry;
int i, ret;
+ if (c->opts.nochanges)
+ return 0;
+
trace_bcache_prio_write_start(ca);
atomic64_add(ca->mi.bucket_size * prio_buckets(ca),
diff --git a/drivers/md/bcache/btree_cache.c b/drivers/md/bcache/btree_cache.c
index 099419067138..342b53a8cb4b 100644
--- a/drivers/md/bcache/btree_cache.c
+++ b/drivers/md/bcache/btree_cache.c
@@ -149,7 +149,8 @@ static int mca_reap_notrace(struct cache_set *c, struct btree *b, bool flush)
if (!six_trylock_write(&b->lock))
goto out_unlock_intent;
- if (btree_node_write_error(b))
+ if (btree_node_write_error(b) ||
+ btree_node_noevict(b))
goto out_unlock;
if (!list_empty(&b->write_blocked))
diff --git a/drivers/md/bcache/btree_io.c b/drivers/md/bcache/btree_io.c
index e7a8a194feff..4c295af1803e 100644
--- a/drivers/md/bcache/btree_io.c
+++ b/drivers/md/bcache/btree_io.c
@@ -1443,8 +1443,9 @@ void __bch_btree_node_write(struct cache_set *c, struct btree *b,
* Make sure to update b->written so bch_btree_init_next() doesn't
* break:
*/
- if (bch_journal_error(&c->journal)) {
- set_btree_node_write_error(b);
+ if (bch_journal_error(&c->journal) ||
+ c->opts.nochanges) {
+ set_btree_node_noevict(b);
b->written += sectors_to_write;
btree_bounce_free(c, order, used_mempool, data);
diff --git a/drivers/md/bcache/btree_types.h b/drivers/md/bcache/btree_types.h
index 4e936cc09b06..176d42a7a434 100644
--- a/drivers/md/bcache/btree_types.h
+++ b/drivers/md/bcache/btree_types.h
@@ -139,6 +139,7 @@ enum btree_flags {
BTREE_NODE_read_error,
BTREE_NODE_write_error,
BTREE_NODE_dirty,
+ BTREE_NODE_noevict,
BTREE_NODE_write_idx,
BTREE_NODE_accessed,
BTREE_NODE_write_in_flight,
@@ -148,6 +149,7 @@ enum btree_flags {
BTREE_FLAG(read_error);
BTREE_FLAG(write_error);
BTREE_FLAG(dirty);
+BTREE_FLAG(noevict);
BTREE_FLAG(write_idx);
BTREE_FLAG(accessed);
BTREE_FLAG(write_in_flight);
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 1be2e607228c..11c64b52068b 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -46,6 +46,9 @@ void __bch_btree_verify(struct cache_set *c, struct btree *b)
struct bio *bio;
struct closure cl;
+ if (c->opts.nochanges)
+ return;
+
closure_init_stack(&cl);
btree_node_io_lock(b);
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 7219b658dd05..4112ea50c472 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -140,6 +140,8 @@ void bch_submit_wbio_replicas(struct bch_write_bio *wbio, struct cache_set *c,
struct bch_write_bio *n;
struct cache *ca;
+ BUG_ON(c->opts.nochanges);
+
wbio->split = false;
wbio->c = c;
@@ -738,7 +740,8 @@ void bch_write(struct closure *cl)
!(op->flags & BCH_WRITE_CACHED),
op->flags & BCH_WRITE_DISCARD);
- if (!percpu_ref_tryget(&c->writes)) {
+ if (c->opts.nochanges ||
+ !percpu_ref_tryget(&c->writes)) {
__bcache_io_error(c, "read only");
op->error = -EROFS;
bch_disk_reservation_put(c, &op->res);
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 32306bc19e9b..9e09b86df1df 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -2065,6 +2065,13 @@ static void journal_write(struct closure *cl)
bch_check_mark_super(c, &j->key, true);
+ /*
+ * XXX: we really should just disable the entire journal in nochanges
+ * mode
+ */
+ if (c->opts.nochanges)
+ goto no_io;
+
extent_for_each_ptr(bkey_i_to_s_extent(&j->key), ptr) {
rcu_read_lock();
ca = PTR_CACHE(c, ptr);
@@ -2094,8 +2101,6 @@ static void journal_write(struct closure *cl)
trace_bcache_journal_write(bio);
closure_bio_submit_punt(bio, cl, c);
- ptr->offset += sectors;
-
ca->journal.bucket_seq[ca->journal.cur_idx] = le64_to_cpu(w->data->seq);
}
@@ -2114,6 +2119,10 @@ static void journal_write(struct closure *cl)
closure_bio_submit_punt(bio, cl, c);
}
+no_io:
+ extent_for_each_ptr(bkey_i_to_s_extent(&j->key), ptr)
+ ptr->offset += sectors;
+
closure_return_with_destructor(cl, journal_write_done);
}
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 3c85d491fec4..22ee5dfd879f 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -274,6 +274,9 @@ int bch_moving_gc_thread_start(struct cache *ca)
/* The moving gc read thread must be stopped */
BUG_ON(ca->moving_gc_read != NULL);
+ if (ca->set->opts.nochanges)
+ return 0;
+
if (cache_set_init_fault("moving_gc_start"))
return -ENOMEM;
diff --git a/drivers/md/bcache/opts.h b/drivers/md/bcache/opts.h
index fe0de7ca0b6a..202f4aebae96 100644
--- a/drivers/md/bcache/opts.h
+++ b/drivers/md/bcache/opts.h
@@ -54,6 +54,12 @@ LE64_BITMASK(NO_SB_OPT, struct cache_sb, flags, 0, 0);
CACHE_SET_OPT(read_only, \
bch_bool_opt, 0, 2, \
NO_SB_OPT, 0) \
+ CACHE_SET_OPT(nochanges, \
+ bch_bool_opt, 0, 2, \
+ NO_SB_OPT, 0) \
+ CACHE_SET_OPT(norecovery, \
+ bch_bool_opt, 0, 2, \
+ NO_SB_OPT, 0) \
CACHE_SET_VISIBLE_OPTS()
struct cache_set_opts {
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 9dad8f13e8f5..3f64e1075b43 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -99,14 +99,17 @@ static bool bch_is_open(struct block_device *bdev)
}
static const char *bch_blkdev_open(const char *path, void *holder,
+ struct cache_set_opts opts,
struct block_device **ret)
{
struct block_device *bdev;
+ fmode_t mode = opts.nochanges > 0
+ ? FMODE_READ
+ : FMODE_READ|FMODE_WRITE|FMODE_EXCL;
const char *err;
*ret = NULL;
- bdev = blkdev_get_by_path(path, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
- holder);
+ bdev = blkdev_get_by_path(path, mode, holder);
if (bdev == ERR_PTR(-EBUSY)) {
bdev = lookup_bdev(path);
@@ -369,6 +372,7 @@ int bch_super_realloc(struct bcache_superblock *sb, unsigned u64s)
}
static const char *read_super(struct bcache_superblock *sb,
+ struct cache_set_opts opts,
const char *path)
{
const char *err;
@@ -378,7 +382,7 @@ static const char *read_super(struct bcache_superblock *sb,
memset(sb, 0, sizeof(*sb));
- err = bch_blkdev_open(path, &sb, &sb->bdev);
+ err = bch_blkdev_open(path, &sb, opts, &sb->bdev);
if (err)
return err;
retry:
@@ -614,6 +618,9 @@ static void __bcache_write_super(struct cache_set *c)
closure_init(cl, &c->cl);
+ if (c->opts.nochanges)
+ goto no_io;
+
le64_add_cpu(&c->disk_sb.seq, 1);
for_each_cache(ca, c, i) {
@@ -636,7 +643,7 @@ static void __bcache_write_super(struct cache_set *c)
percpu_ref_get(&ca->ref);
__write_super(c, &ca->disk_sb);
}
-
+no_io:
closure_return_with_destructor(cl, bcache_write_super_unlock);
}
@@ -1147,6 +1154,9 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb,
c->opts = cache_superblock_opts(sb);
cache_set_opts_apply(&c->opts, opts);
+ c->opts.nochanges |= c->opts.norecovery;
+ c->opts.read_only |= c->opts.nochanges;
+
c->block_bits = ilog2(c->sb.block_size);
if (cache_set_init_fault("cache_set_alloc"))
@@ -1339,6 +1349,11 @@ static const char *run_cache_set(struct cache_set *c)
if (bch_initial_gc(c, &journal))
goto err;
+ if (c->opts.norecovery) {
+ bch_journal_entries_free(&journal);
+ goto recovery_done;
+ }
+
bch_verbose(c, "mark and sweep done");
/*
@@ -1437,7 +1452,7 @@ static const char *run_cache_set(struct cache_set *c)
if (bch_journal_meta(&c->journal))
goto err;
}
-
+recovery_done:
if (c->opts.read_only) {
bch_cache_set_read_only_sync(c);
} else {
@@ -2105,7 +2120,7 @@ int bch_cache_set_add_cache(struct cache_set *c, const char *path)
mutex_lock(&bch_register_lock);
- err = read_super(&sb, path);
+ err = read_super(&sb, c->opts, path);
if (err)
goto err_unlock;
@@ -2249,7 +2264,7 @@ const char *bch_register_cache_set(char * const *devices, unsigned nr_devices,
mutex_lock(&bch_register_lock);
for (i = 0; i < nr_devices; i++) {
- err = read_super(&sb[i], devices[i]);
+ err = read_super(&sb[i], opts, devices[i]);
if (err)
goto err_unlock;
@@ -2314,18 +2329,19 @@ err:
const char *bch_register_one(const char *path)
{
struct bcache_superblock sb;
+ struct cache_set_opts opts = cache_set_opts_empty();
const char *err;
mutex_lock(&bch_register_lock);
- err = read_super(&sb, path);
+ err = read_super(&sb, opts, path);
if (err)
goto err;
if (__SB_IS_BDEV(le64_to_cpu(sb.sb->version)))
err = bch_backing_dev_register(&sb);
else
- err = register_cache(&sb, cache_set_opts_empty());
+ err = register_cache(&sb, opts);
free_super(&sb);
err:
diff --git a/drivers/md/bcache/tier.c b/drivers/md/bcache/tier.c
index 2b568e1f8c33..39b04f7b234b 100644
--- a/drivers/md/bcache/tier.c
+++ b/drivers/md/bcache/tier.c
@@ -224,6 +224,9 @@ int bch_tiering_read_start(struct cache_set *c)
{
struct task_struct *t;
+ if (c->opts.nochanges)
+ return 0;
+
t = kthread_create(bch_tiering_thread, c, "bch_tier_read");
if (IS_ERR(t))
return PTR_ERR(t);