diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-03-22 18:31:06 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 12:35:52 -0800 |
commit | 3fd45422ddede9a8c6ba107c599152fc12ac85a0 (patch) | |
tree | c075b4ad9d6d3d28cb688378fea00694a65c7140 | |
parent | c40268dc94d103abcf20ae8057b7808d7ad402fc (diff) |
bcache: block bch_write() caller on alloc failure
else things such as writeback can queue up unlimited numbers of writes
-rw-r--r-- | drivers/md/bcache/io.c | 32 | ||||
-rw-r--r-- | drivers/md/bcache/io.h | 1 |
2 files changed, 25 insertions, 8 deletions
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 266b83bbee8b..9dad04182c35 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -593,6 +593,8 @@ static void bch_write_index(struct closure *cl) u64 sectors_start = keylist_sectors(&op->insert_keys); int ret; + op->flags |= BCH_WRITE_LOOPED; + ret = bch_btree_insert(op->c, BTREE_ID_EXTENTS, &op->insert_keys, &op->res, @@ -1025,15 +1027,29 @@ static void __bch_write(struct closure *cl) BUG_ON(!b); if (PTR_ERR(b) == -EAGAIN) { - /* If we already have some keys, must insert them first + /* + * If we already have some keys, must insert them first * before allocating another open bucket. We only hit - * this case if open_bucket_nr > 1. */ - if (bch_keylist_empty(&op->insert_keys)) - continue_at(cl, __bch_write, - op->io_wq); - else - continue_at(cl, bch_write_index, - op->c->wq); + * this case if open_bucket_nr > 1. + */ + if (!bch_keylist_empty(&op->insert_keys)) + continue_at(cl, bch_write_index, op->c->wq); + + /* + * If we've looped, we're running out of a workqueue - + * not the bch_write() caller's context - and we don't + * want to block the workqueue: + */ + if (op->flags & BCH_WRITE_LOOPED) + continue_at(cl, __bch_write, op->io_wq); + + /* + * Otherwise, we do want to block the caller on alloc + * failure instead of letting it queue up more and more + * writes: + */ + closure_sync(cl); + continue; } else if (IS_ERR(b)) goto err; diff --git a/drivers/md/bcache/io.h b/drivers/md/bcache/io.h index e36b1d7e5edf..ab559632b7b4 100644 --- a/drivers/md/bcache/io.h +++ b/drivers/md/bcache/io.h @@ -26,6 +26,7 @@ enum bch_write_flags { /* Internal: */ BCH_WRITE_JOURNAL_SEQ_PTR = (1 << 5), BCH_WRITE_DONE = (1 << 6), + BCH_WRITE_LOOPED = (1 << 7), }; void bch_write_op_init(struct bch_write_op *, struct cache_set *, |