aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Swenson <nks@daterainc.com>2014-01-09 19:03:04 -0500
committerKent Overstreet <kmo@daterainc.com>2014-03-18 15:22:33 -0400
commitda415a096fc06e49d1a15f7a06bcfe6ad44c5d38 (patch)
tree54a5b937d4acd579f43b9dc062afd41ecaa33d82
parent90db6919f5f1614d1b7a92052445506bc6c564d2 (diff)
bcache: Fix moving_gc deadlocking with a foreground write
Deadlock happened because a foreground write slept, waiting for a bucket to be allocated. Normally the gc would mark buckets available for invalidation. But the moving_gc was stuck waiting for outstanding writes to complete. These writes used the bcache_wq, the same queue foreground writes used. This fix gives moving_gc its own work queue, so it was still finish moving even if foreground writes are stuck waiting for allocation. It also makes work queue a parameter to the data_insert path, so moving_gc can use its workqueue for writes. Signed-off-by: Nicholas Swenson <nks@daterainc.com> Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r--drivers/md/bcache/bcache.h2
-rw-r--r--drivers/md/bcache/movinggc.c5
-rw-r--r--drivers/md/bcache/request.c13
-rw-r--r--drivers/md/bcache/request.h1
-rw-r--r--drivers/md/bcache/super.c3
5 files changed, 16 insertions, 8 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index a4c7306ff43d..6d814f463d9e 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -628,6 +628,8 @@ struct cache_set {
628 /* Number of moving GC bios in flight */ 628 /* Number of moving GC bios in flight */
629 struct semaphore moving_in_flight; 629 struct semaphore moving_in_flight;
630 630
631 struct workqueue_struct *moving_gc_wq;
632
631 struct btree *root; 633 struct btree *root;
632 634
633#ifdef CONFIG_BCACHE_DEBUG 635#ifdef CONFIG_BCACHE_DEBUG
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 9eb60d102de8..8c7205186d08 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -115,7 +115,7 @@ static void write_moving(struct closure *cl)
115 closure_call(&op->cl, bch_data_insert, NULL, cl); 115 closure_call(&op->cl, bch_data_insert, NULL, cl);
116 } 116 }
117 117
118 continue_at(cl, write_moving_finish, system_wq); 118 continue_at(cl, write_moving_finish, op->wq);
119} 119}
120 120
121static void read_moving_submit(struct closure *cl) 121static void read_moving_submit(struct closure *cl)
@@ -125,7 +125,7 @@ static void read_moving_submit(struct closure *cl)
125 125
126 bch_submit_bbio(bio, io->op.c, &io->w->key, 0); 126 bch_submit_bbio(bio, io->op.c, &io->w->key, 0);
127 127
128 continue_at(cl, write_moving, system_wq); 128 continue_at(cl, write_moving, io->op.wq);
129} 129}
130 130
131static void read_moving(struct cache_set *c) 131static void read_moving(struct cache_set *c)
@@ -160,6 +160,7 @@ static void read_moving(struct cache_set *c)
160 io->w = w; 160 io->w = w;
161 io->op.inode = KEY_INODE(&w->key); 161 io->op.inode = KEY_INODE(&w->key);
162 io->op.c = c; 162 io->op.c = c;
163 io->op.wq = c->moving_gc_wq;
163 164
164 moving_init(io); 165 moving_init(io);
165 bio = &io->bio.bio; 166 bio = &io->bio.bio;
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index fc14ba3f6d05..3e880869871f 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -248,7 +248,7 @@ static void bch_data_insert_keys(struct closure *cl)
248 atomic_dec_bug(journal_ref); 248 atomic_dec_bug(journal_ref);
249 249
250 if (!op->insert_data_done) 250 if (!op->insert_data_done)
251 continue_at(cl, bch_data_insert_start, bcache_wq); 251 continue_at(cl, bch_data_insert_start, op->wq);
252 252
253 bch_keylist_free(&op->insert_keys); 253 bch_keylist_free(&op->insert_keys);
254 closure_return(cl); 254 closure_return(cl);
@@ -297,7 +297,7 @@ static void bch_data_invalidate(struct closure *cl)
297 op->insert_data_done = true; 297 op->insert_data_done = true;
298 bio_put(bio); 298 bio_put(bio);
299out: 299out:
300 continue_at(cl, bch_data_insert_keys, bcache_wq); 300 continue_at(cl, bch_data_insert_keys, op->wq);
301} 301}
302 302
303static void bch_data_insert_error(struct closure *cl) 303static void bch_data_insert_error(struct closure *cl)
@@ -340,7 +340,7 @@ static void bch_data_insert_endio(struct bio *bio, int error)
340 if (op->writeback) 340 if (op->writeback)
341 op->error = error; 341 op->error = error;
342 else if (!op->replace) 342 else if (!op->replace)
343 set_closure_fn(cl, bch_data_insert_error, bcache_wq); 343 set_closure_fn(cl, bch_data_insert_error, op->wq);
344 else 344 else
345 set_closure_fn(cl, NULL, NULL); 345 set_closure_fn(cl, NULL, NULL);
346 } 346 }
@@ -376,7 +376,7 @@ static void bch_data_insert_start(struct closure *cl)
376 if (bch_keylist_realloc(&op->insert_keys, 376 if (bch_keylist_realloc(&op->insert_keys,
377 3 + (op->csum ? 1 : 0), 377 3 + (op->csum ? 1 : 0),
378 op->c)) 378 op->c))
379 continue_at(cl, bch_data_insert_keys, bcache_wq); 379 continue_at(cl, bch_data_insert_keys, op->wq);
380 380
381 k = op->insert_keys.top; 381 k = op->insert_keys.top;
382 bkey_init(k); 382 bkey_init(k);
@@ -413,7 +413,7 @@ static void bch_data_insert_start(struct closure *cl)
413 } while (n != bio); 413 } while (n != bio);
414 414
415 op->insert_data_done = true; 415 op->insert_data_done = true;
416 continue_at(cl, bch_data_insert_keys, bcache_wq); 416 continue_at(cl, bch_data_insert_keys, op->wq);
417err: 417err:
418 /* bch_alloc_sectors() blocks if s->writeback = true */ 418 /* bch_alloc_sectors() blocks if s->writeback = true */
419 BUG_ON(op->writeback); 419 BUG_ON(op->writeback);
@@ -442,7 +442,7 @@ err:
442 bio_put(bio); 442 bio_put(bio);
443 443
444 if (!bch_keylist_empty(&op->insert_keys)) 444 if (!bch_keylist_empty(&op->insert_keys))
445 continue_at(cl, bch_data_insert_keys, bcache_wq); 445 continue_at(cl, bch_data_insert_keys, op->wq);
446 else 446 else
447 closure_return(cl); 447 closure_return(cl);
448 } 448 }
@@ -824,6 +824,7 @@ static inline struct search *search_alloc(struct bio *bio,
824 s->iop.error = 0; 824 s->iop.error = 0;
825 s->iop.flags = 0; 825 s->iop.flags = 0;
826 s->iop.flush_journal = (bio->bi_rw & (REQ_FLUSH|REQ_FUA)) != 0; 826 s->iop.flush_journal = (bio->bi_rw & (REQ_FLUSH|REQ_FUA)) != 0;
827 s->iop.wq = bcache_wq;
827 828
828 return s; 829 return s;
829} 830}
diff --git a/drivers/md/bcache/request.h b/drivers/md/bcache/request.h
index 39f21dbedc38..c117c4082aa2 100644
--- a/drivers/md/bcache/request.h
+++ b/drivers/md/bcache/request.h
@@ -7,6 +7,7 @@ struct data_insert_op {
7 struct closure cl; 7 struct closure cl;
8 struct cache_set *c; 8 struct cache_set *c;
9 struct bio *bio; 9 struct bio *bio;
10 struct workqueue_struct *wq;
10 11
11 unsigned inode; 12 unsigned inode;
12 uint16_t write_point; 13 uint16_t write_point;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index fb343276beef..ddfde380b49f 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1356,6 +1356,8 @@ static void cache_set_free(struct closure *cl)
1356 bch_bset_sort_state_free(&c->sort); 1356 bch_bset_sort_state_free(&c->sort);
1357 free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c))); 1357 free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c)));
1358 1358
1359 if (c->moving_gc_wq)
1360 destroy_workqueue(c->moving_gc_wq);
1359 if (c->bio_split) 1361 if (c->bio_split)
1360 bioset_free(c->bio_split); 1362 bioset_free(c->bio_split);
1361 if (c->fill_iter) 1363 if (c->fill_iter)
@@ -1522,6 +1524,7 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
1522 !(c->fill_iter = mempool_create_kmalloc_pool(1, iter_size)) || 1524 !(c->fill_iter = mempool_create_kmalloc_pool(1, iter_size)) ||
1523 !(c->bio_split = bioset_create(4, offsetof(struct bbio, bio))) || 1525 !(c->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
1524 !(c->uuids = alloc_bucket_pages(GFP_KERNEL, c)) || 1526 !(c->uuids = alloc_bucket_pages(GFP_KERNEL, c)) ||
1527 !(c->moving_gc_wq = create_workqueue("bcache_gc")) ||
1525 bch_journal_alloc(c) || 1528 bch_journal_alloc(c) ||
1526 bch_btree_cache_alloc(c) || 1529 bch_btree_cache_alloc(c) ||
1527 bch_open_buckets_alloc(c) || 1530 bch_open_buckets_alloc(c) ||