diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2017-02-02 16:38:10 -0900 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2017-02-06 20:43:39 -0900 |
commit | 53cbdcd2d4b1eaa205ff76b91204049d4c314342 (patch) | |
tree | 9606c5f1610cc209ed72a800115a765cfc280b34 | |
parent | c8f34d5c7c93d19023a20e612455e91a5775f0e3 (diff) |
bcache: Add an internal option to disable all filesystem changes
will be used by fsck
-rw-r--r-- | drivers/md/bcache/alloc.c | 3 | ||||
-rw-r--r-- | drivers/md/bcache/btree_cache.c | 3 | ||||
-rw-r--r-- | drivers/md/bcache/btree_io.c | 5 | ||||
-rw-r--r-- | drivers/md/bcache/btree_types.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/debug.c | 3 | ||||
-rw-r--r-- | drivers/md/bcache/io.c | 5 | ||||
-rw-r--r-- | drivers/md/bcache/journal.c | 13 | ||||
-rw-r--r-- | drivers/md/bcache/movinggc.c | 3 | ||||
-rw-r--r-- | drivers/md/bcache/opts.h | 6 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 34 | ||||
-rw-r--r-- | drivers/md/bcache/tier.c | 3 |
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); |