diff options
author | Coly Li <colyli@suse.de> | 2018-11-29 23:55:15 +0800 |
---|---|---|
committer | Coly Li <colyli@suse.de> | 2018-11-29 23:55:15 +0800 |
commit | 1476ea9612e1484408fbe17390b962dadf00740d (patch) | |
tree | 9e268820fd539b6bf17235ebde2cd66be2ed0085 | |
parent | c79775fa12db25ef43f07ed4e7e150bec12d8379 (diff) | |
download | bcache-patches-1476ea9612e1484408fbe17390b962dadf00740d.tar.gz |
for-test: add 0001-bcache-fix-potential-journal-hang-or-dead-locking.patch
-rw-r--r-- | for-test/0001-bcache-fix-potential-journal-hang-or-dead-locking.patch | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/for-test/0001-bcache-fix-potential-journal-hang-or-dead-locking.patch b/for-test/0001-bcache-fix-potential-journal-hang-or-dead-locking.patch new file mode 100644 index 0000000..850b47f --- /dev/null +++ b/for-test/0001-bcache-fix-potential-journal-hang-or-dead-locking.patch @@ -0,0 +1,198 @@ +From f91e782b8d1382d41863ebff431e45721d5171c9 Mon Sep 17 00:00:00 2001 +From: Coly Li <colyli@suse.de> +Date: Thu, 29 Nov 2018 23:53:53 +0800 +Subject: [PATCH] bcache: fix potential journal hang or dead locking + +Signed-off-by: Coly Li <colyli@suse.de> +--- + drivers/md/bcache/btree.c | 2 +- + drivers/md/bcache/journal.c | 65 ++++++++++++++++++++++++++++++++++++++------- + drivers/md/bcache/journal.h | 12 +++++++-- + drivers/md/bcache/request.c | 6 +++-- + 4 files changed, 71 insertions(+), 14 deletions(-) + +diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c +index 3f4211b5cd33..2e671f39acf6 100644 +--- a/drivers/md/bcache/btree.c ++++ b/drivers/md/bcache/btree.c +@@ -2327,7 +2327,7 @@ void bch_btree_set_root(struct btree *b) + + b->c->root = b; + +- bch_journal_meta(b->c, &cl); ++ __bch_journal_meta(b->c, &cl, BCH_JOURNAL_USE_RESV); + closure_sync(&cl); + } + +diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c +index 522c7426f3a0..d2ce56523818 100644 +--- a/drivers/md/bcache/journal.c ++++ b/drivers/md/bcache/journal.c +@@ -707,8 +707,48 @@ static void journal_try_write(struct cache_set *c) + } + } + ++static inline bool no_journal_wait(struct cache_set *c, ++ size_t sectors, ++ int journal_flags) ++{ ++ /* no access to reserved journal space */ ++ if (!(journal_flags & BCH_JOURNAL_USE_RESV) && ++ sectors < min_t(size_t, ++ c->journal.blocks_free * c->sb.block_size ++ - JOURNAL_BLK_RSV, ++ PAGE_SECTORS << JSET_BITS)) ++ return true; ++ ++ /* has access to reserved journal space */ ++ if ((journal_flags & BCH_JOURNAL_USE_RESV) && ++ sectors <= min_t(size_t, ++ c->journal.blocks_free * c->sb.block_size, ++ PAGE_SECTORS << JSET_BITS)) ++ return true; ++ ++ return false; ++} ++ ++static inline bool no_journal_reclaim(struct cache_set *c, ++ int journal_flags) ++{ ++ /* no access to reserved journal space and pin */ ++ if (!(journal_flags & BCH_JOURNAL_USE_RESV) && ++ fifo_free(&(&c->journal)->pin) > (JOURNAL_PIN_RSV + 1) && ++ c->journal.blocks_free > JOURNAL_BLK_RSV) ++ return true; ++ ++ /* has access to reserved journal space and pin*/ ++ if ((journal_flags & BCH_JOURNAL_USE_RESV) && ++ !journal_full(&c->journal)) ++ return true; ++ ++ return false; ++} ++ + static struct journal_write *journal_wait_for_write(struct cache_set *c, +- unsigned int nkeys) ++ unsigned int nkeys, ++ int journal_flags) + __acquires(&c->journal.lock) + { + size_t sectors; +@@ -725,15 +765,13 @@ static struct journal_write *journal_wait_for_write(struct cache_set *c, + sectors = __set_blocks(w->data, w->data->keys + nkeys, + block_bytes(c)) * c->sb.block_size; + +- if (sectors <= min_t(size_t, +- c->journal.blocks_free * c->sb.block_size, +- PAGE_SECTORS << JSET_BITS)) ++ if (no_journal_wait(c, sectors, journal_flags)) + return w; + + if (wait) + closure_wait(&c->journal.wait, &cl); + +- if (!journal_full(&c->journal)) { ++ if (no_journal_reclaim(c, journal_flags)){ + if (wait) + trace_bcache_journal_entry_full(c); + +@@ -782,7 +820,8 @@ static void journal_write_work(struct work_struct *work) + + atomic_t *bch_journal(struct cache_set *c, + struct keylist *keys, +- struct closure *parent) ++ struct closure *parent, ++ int journal_flags) + { + struct journal_write *w; + atomic_t *ret; +@@ -790,7 +829,7 @@ atomic_t *bch_journal(struct cache_set *c, + if (!CACHE_SYNC(&c->sb)) + return NULL; + +- w = journal_wait_for_write(c, bch_keylist_nkeys(keys)); ++ w = journal_wait_for_write(c, bch_keylist_nkeys(keys), journal_flags); + + memcpy(bset_bkey_last(w->data), keys->keys, bch_keylist_bytes(keys)); + w->data->keys += bch_keylist_nkeys(keys); +@@ -814,18 +853,26 @@ atomic_t *bch_journal(struct cache_set *c, + return ret; + } + +-void bch_journal_meta(struct cache_set *c, struct closure *cl) ++void __bch_journal_meta(struct cache_set *c, ++ struct closure *cl, ++ int journal_flags) + { + struct keylist keys; + atomic_t *ref; + + bch_keylist_init(&keys); + +- ref = bch_journal(c, &keys, cl); ++ ref = bch_journal(c, &keys, cl, journal_flags); + if (ref) + atomic_dec_bug(ref); + } + ++void bch_journal_meta(struct cache_set *c, ++ struct closure *cl) ++{ ++ __bch_journal_meta(c, cl, 0); ++} ++ + void bch_journal_free(struct cache_set *c) + { + free_pages((unsigned long) c->journal.w[1].data, JSET_BITS); +diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h +index 66f0facff84b..411fb0860d64 100644 +--- a/drivers/md/bcache/journal.h ++++ b/drivers/md/bcache/journal.h +@@ -157,7 +157,11 @@ struct journal_device { + #define journal_pin_cmp(c, l, r) \ + (fifo_idx(&(c)->journal.pin, (l)) > fifo_idx(&(c)->journal.pin, (r))) + +-#define JOURNAL_PIN 20000 ++#define BCH_JOURNAL_USE_RESV 1 ++ ++#define JOURNAL_PIN 20000 ++#define JOURNAL_PIN_RSV 1 ++#define JOURNAL_BLK_RSV (PAGE_SECTORS << JSET_BITS) + + #define journal_full(j) \ + (!(j)->blocks_free || fifo_free(&(j)->pin) <= 1) +@@ -169,9 +173,13 @@ struct keylist; + + atomic_t *bch_journal(struct cache_set *c, + struct keylist *keys, +- struct closure *parent); ++ struct closure *parent, ++ int journal_flags); + void bch_journal_next(struct journal *j); + void bch_journal_mark(struct cache_set *c, struct list_head *list); ++void __bch_journal_meta(struct cache_set *c, ++ struct closure *cl, ++ int journal_flags); + void bch_journal_meta(struct cache_set *c, struct closure *cl); + int bch_journal_read(struct cache_set *c, struct list_head *list); + int bch_journal_replay(struct cache_set *c, struct list_head *list); +diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c +index 3bf35914bb57..20e31ecb73c0 100644 +--- a/drivers/md/bcache/request.c ++++ b/drivers/md/bcache/request.c +@@ -75,8 +75,10 @@ static void bch_data_insert_keys(struct closure *cl) + #endif + + if (!op->replace) +- journal_ref = bch_journal(op->c, &op->insert_keys, +- op->flush_journal ? cl : NULL); ++ journal_ref = bch_journal(op->c, ++ &op->insert_keys, ++ op->flush_journal ? cl : NULL, ++ 0); + + ret = bch_btree_insert(op->c, &op->insert_keys, + journal_ref, replace_key); +-- +2.16.4 + |