aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColy Li <colyli@suse.de>2018-11-29 23:55:15 +0800
committerColy Li <colyli@suse.de>2018-11-29 23:55:15 +0800
commit1476ea9612e1484408fbe17390b962dadf00740d (patch)
tree9e268820fd539b6bf17235ebde2cd66be2ed0085
parentc79775fa12db25ef43f07ed4e7e150bec12d8379 (diff)
downloadbcache-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.patch198
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
+