Skip to content

Commit 0f843e6

Browse files
goldhornaxboe
authored andcommitted
bcache: add separate workqueue for journal_write to avoid deadlock
After write SSD completed, bcache schedules journal_write work to system_wq, which is a public workqueue in system, without WQ_MEM_RECLAIM flag. system_wq is also a bound wq, and there may be no idle kworker on current processor. Creating a new kworker may unfortunately need to reclaim memory first, by shrinking cache and slab used by vfs, which depends on bcache device. That's a deadlock. This patch create a new workqueue for journal_write with WQ_MEM_RECLAIM flag. It's rescuer thread will work to avoid the deadlock. Signed-off-by: Guoju Fang <fangguoju@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Coly Li <colyli@suse.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent f151ba9 commit 0f843e6

File tree

3 files changed

+12
-3
lines changed

3 files changed

+12
-3
lines changed

drivers/md/bcache/bcache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,7 @@ void bch_prio_write(struct cache *ca);
965965
void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent);
966966

967967
extern struct workqueue_struct *bcache_wq;
968+
extern struct workqueue_struct *bch_journal_wq;
968969
extern struct mutex bch_register_lock;
969970
extern struct list_head bch_cache_sets;
970971

drivers/md/bcache/journal.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ static void do_journal_discard(struct cache *ca)
485485

486486
closure_get(&ca->set->cl);
487487
INIT_WORK(&ja->discard_work, journal_discard_work);
488-
schedule_work(&ja->discard_work);
488+
queue_work(bch_journal_wq, &ja->discard_work);
489489
}
490490
}
491491

@@ -592,7 +592,7 @@ static void journal_write_done(struct closure *cl)
592592
: &j->w[0];
593593

594594
__closure_wake_up(&w->wait);
595-
continue_at_nobarrier(cl, journal_write, system_wq);
595+
continue_at_nobarrier(cl, journal_write, bch_journal_wq);
596596
}
597597

598598
static void journal_write_unlock(struct closure *cl)
@@ -627,7 +627,7 @@ static void journal_write_unlocked(struct closure *cl)
627627
spin_unlock(&c->journal.lock);
628628

629629
btree_flush_write(c);
630-
continue_at(cl, journal_write, system_wq);
630+
continue_at(cl, journal_write, bch_journal_wq);
631631
return;
632632
}
633633

drivers/md/bcache/super.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static int bcache_major;
4747
static DEFINE_IDA(bcache_device_idx);
4848
static wait_queue_head_t unregister_wait;
4949
struct workqueue_struct *bcache_wq;
50+
struct workqueue_struct *bch_journal_wq;
5051

5152
#define BTREE_MAX_PAGES (256 * 1024 / PAGE_SIZE)
5253
/* limitation of partitions number on single bcache device */
@@ -2341,6 +2342,9 @@ static void bcache_exit(void)
23412342
kobject_put(bcache_kobj);
23422343
if (bcache_wq)
23432344
destroy_workqueue(bcache_wq);
2345+
if (bch_journal_wq)
2346+
destroy_workqueue(bch_journal_wq);
2347+
23442348
if (bcache_major)
23452349
unregister_blkdev(bcache_major, "bcache");
23462350
unregister_reboot_notifier(&reboot);
@@ -2370,6 +2374,10 @@ static int __init bcache_init(void)
23702374
if (!bcache_wq)
23712375
goto err;
23722376

2377+
bch_journal_wq = alloc_workqueue("bch_journal", WQ_MEM_RECLAIM, 0);
2378+
if (!bch_journal_wq)
2379+
goto err;
2380+
23732381
bcache_kobj = kobject_create_and_add("bcache", fs_kobj);
23742382
if (!bcache_kobj)
23752383
goto err;

0 commit comments

Comments
 (0)