summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-03-22 18:31:06 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:35:52 -0800
commit3fd45422ddede9a8c6ba107c599152fc12ac85a0 (patch)
treec075b4ad9d6d3d28cb688378fea00694a65c7140
parentc40268dc94d103abcf20ae8057b7808d7ad402fc (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.c32
-rw-r--r--drivers/md/bcache/io.h1
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 *,